0

Trying to use Class shown here as a sample for Activator.CreateInstance() http://codeblocks.codeplex.com/wikipage?title=FasterActivator%20Sample

    public static List<T> SortedCollection<T>(SPListItemCollection items, ListSortType sortType, List<Vote> votes) where T : IVotable
    {
        var returnlist = new List<T>();
        var functionCreator = FastActivator.GenerateFunc<Func<SPListItem, List<Vote>, T>>();

        for (int i = 0; i < items.Count; i++) { returnlist.Add(functionCreator(items[i], votes)); }
        }
        switch (sortType)
        {
            case ListSortType.Hot:
                returnlist.Sort((p1, p2) => p2.HotScore.CompareTo(p1.HotScore));
                break;
            case ListSortType.Top:
                returnlist.Sort((p1, p2) => p2.VoteTotal.CompareTo(p1.VoteTotal));
                break;
            case ListSortType.Recent:
                returnlist.Sort((p1, p2) => p2.CreatedDate.CompareTo(p1.CreatedDate));
                break;
        }
        return returnlist;
    }

Error is in the for loop, getting MethodAccessException:

.Post__041c49eec0a6466da11894b0455b1162(Microsoft.SharePoint.SPListItem, System.Collections.Generic.List1)`

Console App with Error (requires FastActivator class to be in the same namespace):

namespace testcase
{
    class Program
    {
        static void Main(string[] args)
        {
            var vote1 = new Vote() {ItemID=1};
            List<Vote> votes = new List<Vote>();
            votes.Add(vote1);

            List<string> strings = new List<string>();
            strings.Add("test");
            List<Post> posts = Post.SortedCollection<Post>(strings, ListSortType.Hot, votes);
        }
    }

    internal interface IVotable
    {
        double HotScore { get; set; }
        double VoteTotal { get; set; }
        DateTime CreatedDate { get; set; }
    }
    internal class SCO : IVotable
    {
        public double HotScore { get; set; }
        public double VoteTotal { get; set; }
        public DateTime CreatedDate { get; set; }

        public SCO(string item, List<Vote> votes)
        {
            VoteTotal = 10;
            HotScore = 10;
            CreatedDate = DateTime.Now;
        }

        public static List<T> SortedCollection<T>(List<string> items, ListSortType sortType, List<Vote> votes) where T : IVotable
        {
            var returnlist = new List<T>();
            Type genericType = typeof(T);
            var functionCreator = FastActivator.GenerateFunc<Func<string, List<Vote>, T>>();

            for (int i = 0; i < items.Count; i++) { returnlist.Add(functionCreator(items[i], votes)); }
            switch (sortType)
            {
                case ListSortType.Hot:
                    returnlist.Sort((p1, p2) => p2.HotScore.CompareTo(p1.HotScore));
                    break;
                case ListSortType.Top:
                    returnlist.Sort((p1, p2) => p2.VoteTotal.CompareTo(p1.VoteTotal));
                    break;
                case ListSortType.Recent:
                    returnlist.Sort((p1, p2) => p2.CreatedDate.CompareTo(p1.CreatedDate));
                    break;
            }
            return returnlist;
        }
    }

    class Vote
    {
        public double ItemID { get; set; }
    }
    class VoteMeta
    {
        public double UpVotes { get; set; }
        public double DownVotes { get; set; }
        public string CurrentUserVoteClass { get; set; }
    }
    internal enum ListSortType { Hot, Top, Recent };

    class Post : SCO
    {
        public string Summary { get; set; }
        public Uri Link { get; set; }

        public Post(string item, List<Vote> votes)
            : base(item, votes)
        {
            Summary = "Summary";
            Link = new UriBuilder("http://www.google.com").Uri;
        }
    }
}
Wesley
  • 5,381
  • 9
  • 42
  • 65
  • Is that constructor you're accessing public? – Ani Aug 27 '12 at 20:05
  • Yes, on both the base class and the child class – Wesley Aug 27 '12 at 20:06
  • Do you have a standalone sample that shows this problem - using dummy classes instead of the real ones? I can try it out and see what the problem could be. – Ani Aug 27 '12 at 20:08
  • I can try to write a simple console app or something, going to take some time. – Wesley Aug 27 '12 at 20:09
  • I would put a breakpoint in `FastActivator.GenerateFunc`, right after it gets the `constructor` local variable, and see what constructor it's returning. It's very possible that it's returning an overloaded constructor that is not public, rather than the constructor that you're expecting. – Jon Senchyna Aug 27 '12 at 20:31
  • Nope, the IsPublic bool on the constructor is true. – Wesley Aug 27 '12 at 20:40
  • Your classes ARE internal. Not explicitly specifying a visibility makes them internal, not public (http://stackoverflow.com/questions/3763612/default-visibility-for-c-sharp-classes-and-members-fields-methods-etc). These (http://pastebin.com/eZY2tgKy) modifications made the program work correctly. Note that the dynamic method is in a dynamically generated assembly and as such doesn't have access to internal members. – Ani Aug 27 '12 at 20:52
  • My temp solution wasn't identical to my real code, but I did find a class not marked at all, and therefore internal. Changing this did work, if you'd like to submit the answer I will mark it. – Wesley Aug 27 '12 at 21:02
  • Done, glad I could help! I *do* hope you're caching that created method in the REAL code, because your example is generating a new one each time and that's not good! ;) – Ani Aug 27 '12 at 21:05

1 Answers1

3

You probably have a non-public constructor somewhere. Not explicitly specifying a visibility on a namespace member makes it internal, not public. These modifications made your example program work correctly. Note that the dynamic method is in a dynamically generated assembly and as such doesn't have access to internal members.

Community
  • 1
  • 1
Ani
  • 10,826
  • 3
  • 27
  • 46
  • Now to see if there is a way to do this without making API classes public. – Wesley Aug 27 '12 at 21:07
  • I believe this should be possible - I'll post back when I have this functionality added to FastActivator. :) – Ani Aug 27 '12 at 21:14
  • Got it to work. In the methods which return a `DynamicMethod`, add a bool `true` for `restrictedSkipVisibility`. – Wesley Aug 27 '12 at 21:37
  • `new DynamicMethod(string.Format("{0}__{1}", constructor.DeclaringType.Name, Guid.NewGuid().ToString().Replace("-", "")), constructor.DeclaringType, (from param in constructorParams select param.ParameterType).ToArray(), true);` – Wesley Aug 27 '12 at 21:38
  • Very nice, thanks. I'll add that to FastActivator - with your permission, of course. – Ani Aug 28 '12 at 03:56
  • Not specifying a visibility on a class member makes it `private`, not `internal`. – svick Aug 28 '12 at 08:34
  • My bad, I meant a class/enum (any element directly inside a namespace in this instance) - see the link I provided. Will edit. – Ani Aug 28 '12 at 14:03
  • I just pushed an updated package to Nuget, for anyone who lands here and wishes to use this package. – Ani Sep 05 '12 at 20:06