locked
Question about Generics RRS feed

  • Question

  • User1176145865 posted

    Hi

    Ive started this thread in C# but I guess my question now is design architecture moer than syntax..

    My project includes many similar object for different properties:

    doesens of ID, Name type tables..

    It also includes an Alert<T> object..

    all of the classes need to have collections..

    I came a across a solution from "Joanna Carter" using a Delphi type "type of" class implemented in c# as a MetaClass that uses ConstructorInfo and MethodInfo..


    It seems like a better solution since it avoids code redundency.. and provides a "virtual constructor" that c# doesnt have..

    Any comments?


    Thursday, February 4, 2010 4:38 AM

Answers

  • User1176145865 posted

    Hi Aquaren,

    Thanks for the response, this is not what im looking for because what im trying to do is have one method to build all the generic objects. i think i found a way to do it. Heres one example using delegates and an Operator overload "ClassReference" an example posted by Joanna Carter:

    public class Base
        {
            private delegate Base ConstructorDelegate();
            private delegate Base ConstructorDelegateWithParam(int someParam);

            public class ClassReference
            {
                Type currentType = typeof(Base);

                public Base Create<U>(int someParam) where U : Base
                {
                    ConstructorInfo ci = currentType.GetConstructor(BindingFlags.Instance |
                    BindingFlags.Public, null, new Type[] { typeof(int) }, null);
                    DynamicMethod dm = new DynamicMethod("CreateInstance", typeof(Base), new Type[] {
                    typeof(int) }, typeof(ClassReference));
                    ILGenerator il = dm.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Newobj, ci);
                    il.Emit(OpCodes.Ret);
                    ConstructorDelegateWithParam del = (ConstructorDelegateWithParam)dm.CreateDelegate(typeof(ConstructorDelegateWithParam));
                    return del(someParam);
                }

                public Base Create<U>() where U : Base
                {

                    ConstructorInfo ci = currentType.GetConstructor(Type.EmptyTypes);
                    DynamicMethod dm = new DynamicMethod("CreateInstance", typeof(Base), Type.EmptyTypes, typeof(ClassReference));
                    ILGenerator il = dm.GetILGenerator();
                    il.Emit(OpCodes.Newobj, ci);
                    il.Emit(OpCodes.Ret);
                    ConstructorDelegate del = (ConstructorDelegate)dm.CreateDelegate(typeof(ConstructorDelegate));
                    return del();
                }

                private ClassReference(Type type)
                {
                    currentType = type;
                }
                internal ClassReference() { }

                public static implicit operator ClassReference(Type input)
                {
                    if (!typeof(Base).IsAssignableFrom(input))
                        throw new Exception(String.Format("Type {0} must derive from {1}", input,
                        typeof(Base)));
                    return new ClassReference(input);
                }
            }


        }


    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 8, 2010 7:20 AM

All replies

  • User559104930 posted

    Without seeing the code, what you are trying to accomplish is a little difficult to understand. "dozens of ID, Name type tables" sounds like a System.Collections.Generic.Dictionary<int, string> or System.Collections.Generic.KeyValuePair<int,string>. Using the built in classes for this purpose will reduce dozens down to one.

    Thursday, February 4, 2010 8:09 AM
  • User1176145865 posted

    My difficulties arrose when I wanted to implement a collection of Alert<T>.

    I wanted to have an alert for generic objects,

    so with the help of this forum came up with: public AlertCollection<T> : IList<Alert<T>>..

    I used a switch clause for the enum collection types but with AlertCollection<T> ? these are not [ID, NAME] pairs..


    Thursday, February 4, 2010 8:20 AM
  • User1176145865 posted

    The best solution seems to be a dynamic constructor, since the number of <T>'s might grow in the future.. but how do I get a dynamic constructor for an Alert<T> collection if we disregard the type of collection for now.

    Lets use a simple List<Alert<MyObject>>> for example, would I have to use ConstructorInfo and MethodInfo?

    Would have to handle implementation and constructor exceptions..



    Friday, February 5, 2010 5:14 AM
  • User559104930 posted

    Can you please restate what it is you are trying to accomplish and include some sample code?

    Friday, February 5, 2010 7:59 AM
  • User1176145865 posted

    I have an Alert  class that represent alert on certain objects like Sale, Person, Country ..

    I want to have a collection of Alert<T> class so I can get all of the alerts on Sales, People and Countries.

    I dont want to use reflection because of the performance issue, in Factory I can use a switch clause but then I would have to edit the list manually each time theres a new Alert.

    I am looking to build a single constructor regardless of properties or methods of <T>.

    Alert<T> class:

       public class Alert<T> : sObject 
        {
           public DateTime ExpiresAt { get; set; }
           public Message Alertmsg { get; set; }
            public Status AlertStatus { get; set; }
            public User RowOwner { get; set; }
            public DateTime RowTime { get; set; }
            public ProcessStatus RowStatus { get; set; }
    }


    Saturday, February 6, 2010 3:21 AM
  • User559104930 posted

    Is this what you are looking for?

        public class Foo
        {
            public Foo(List<Alert<MyObject>> alerts)
            {
            }
        }
    



    Sunday, February 7, 2010 8:29 AM
  • User1176145865 posted

    Hi Aquaren,

    Thanks for the response, this is not what im looking for because what im trying to do is have one method to build all the generic objects. i think i found a way to do it. Heres one example using delegates and an Operator overload "ClassReference" an example posted by Joanna Carter:

    public class Base
        {
            private delegate Base ConstructorDelegate();
            private delegate Base ConstructorDelegateWithParam(int someParam);

            public class ClassReference
            {
                Type currentType = typeof(Base);

                public Base Create<U>(int someParam) where U : Base
                {
                    ConstructorInfo ci = currentType.GetConstructor(BindingFlags.Instance |
                    BindingFlags.Public, null, new Type[] { typeof(int) }, null);
                    DynamicMethod dm = new DynamicMethod("CreateInstance", typeof(Base), new Type[] {
                    typeof(int) }, typeof(ClassReference));
                    ILGenerator il = dm.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Newobj, ci);
                    il.Emit(OpCodes.Ret);
                    ConstructorDelegateWithParam del = (ConstructorDelegateWithParam)dm.CreateDelegate(typeof(ConstructorDelegateWithParam));
                    return del(someParam);
                }

                public Base Create<U>() where U : Base
                {

                    ConstructorInfo ci = currentType.GetConstructor(Type.EmptyTypes);
                    DynamicMethod dm = new DynamicMethod("CreateInstance", typeof(Base), Type.EmptyTypes, typeof(ClassReference));
                    ILGenerator il = dm.GetILGenerator();
                    il.Emit(OpCodes.Newobj, ci);
                    il.Emit(OpCodes.Ret);
                    ConstructorDelegate del = (ConstructorDelegate)dm.CreateDelegate(typeof(ConstructorDelegate));
                    return del();
                }

                private ClassReference(Type type)
                {
                    currentType = type;
                }
                internal ClassReference() { }

                public static implicit operator ClassReference(Type input)
                {
                    if (!typeof(Base).IsAssignableFrom(input))
                        throw new Exception(String.Format("Type {0} must derive from {1}", input,
                        typeof(Base)));
                    return new ClassReference(input);
                }
            }


        }


    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 8, 2010 7:20 AM
  • User1176145865 posted

    The way to use this is by having the genric class <T> derive from base and use base to instanciate it like so

    Base.ClassReference classRef = typeof(Person);
                Base objectRef = classRef.Create<Person>();




    Monday, February 8, 2010 10:17 AM