Question

I'm using nBuilder to generate some Testdata for my application. First I tested it and it worked fine. An easy Example:

Customer customer = Builder<Customer>
                   .CreateNew()
                   .Build();

Creates a Object and fills all Properties automatically. By Example, if customer Contains the attribute: name, it will fill it with name1 and so on...

Well all this works fine, but I have troubles to do that whole thing dynamically now.

What I'm doing now, is Reflection, I'm iterating through all Entities in my Class and foreach of them there should be generated some Testdata, even lookups and childlists should be filled, but thats not a problem.. My question is, how I'm using the above code with any type?

ANYTYPE object = Builder<ANYTYPE> ...

What I tried:

object entity = null; //The object/Entity
Assembly assembly = Assembly.GetAssembly(typeof(EMI_ERPContext)); //Getting Assembly
Type type = assembly.GetType(entityName); //I know the Type
//entity = Activator.CreateInstance(type); Do I must create an Instance here?
object entity = Builder<dynamic> //The above code.. Tried to put dynamic as Type, but doesnt work
               .CreateNew()
               .Build();
Était-ce utile?

La solution

I tested with a console app (complete here), faking the classes / interfaces / methods of nBuilder.

So this works, but not tried in real context.

The method you could reuse is "TryToReflectBuilder". It could be much less verbose, but I let the "Step by step" code, as it's probably more explicit. ReflectionConsole.Test is used as the "entity to reflect".

namespace ReflectionConsole {
    class Program {
        static void Main(string[] args)
        {

            object test = TryToReflectBuilder("ReflectionConsole.Test");
            Console.ReadKey();
        }

        public static object TryToReflectBuilder(string type)
        {
            //getting the assembly : not same as your way, but... that wasn't a problem for you
            var assembly = Assembly.GetAssembly(typeof(Test));

            //getting the entityType by name.
            var entityType = assembly.GetType(type);

            //The interesting (I hope) part is starting (yeah)
            //get the Builder<T> type
            var builderClassType = typeof(Builder<>);

            //create generic argument for Builder<T> will take the type of our entity (always an array)
            Type[] args = {entityType};

            //pass generic arguments to Builder<T>. Which becomes Builder<entityType>
            var genericBuilderType = builderClassType.MakeGenericType(args);

            //create a new instance of Builder<entityType>
            var builder = Activator.CreateInstance(genericBuilderType);

            //retrieve the "CreateNew" method, which belongs to Builder<T> class
            var createNewMethodInfo = builder.GetType().GetMethod("CreateNew");

            //invoke "CreateNew" from our builder instance which gives us an ObjectBuilder<T>, so now an ObjectBuilder<entityType> (well as an ISingleObjectBuilder<entityType>, but... who minds ;))
            var objectBuilder = createNewMethodInfo.Invoke(builder, null);

            //retrieve the "Build" method, which belongs to ObjectBuilder<T> class
            var buildMethodInfo = objectBuilder.GetType().GetMethod("Build");

            //finally, invoke "Build" from our ObjectBuilder<entityType> instance, which will give us... our entity !
            var result = buildMethodInfo.Invoke(objectBuilder, null);

            //it would be sad to return nothing after all these efforts, no ??
            return result;
        }
    }

    public  class Builder<T>
    {
        public static ISingleObjectBuilder<T> CreateNew()
        {
            Console.WriteLine(string.Format("{0} creating new",typeof(T)));
            return new ObjectBuilder<T>();
        } 
    }

    public interface ISingleObjectBuilder<T> : IBuildable<T>
    {
    }
    public interface IObjectBuilder<T> : ISingleObjectBuilder<T>
    {

    }
    public interface IBuildable<T>
    {
        T Build();
    }

    public class ObjectBuilder<T> : ISingleObjectBuilder<T>
    {
        public T Build()
        {
            Console.WriteLine(string.Format("{0} building myself", typeof(T)));
            return Activator.CreateInstance<T>();
        }
    }

    public class Test
    {
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top