如何将类型与另一个组件中的工厂例程配对?

时间:2012-05-23 15:16:21

标签: c# reflection

我正在尝试在我的程序中创建一个通用例程来为我实例化对象。实际负责调用新Object()的例程位于必须实例化的工厂中的不同程序集中。

namespace ExternalLib
{
    class Object1Factory
    {
        public Object1 getObject1()
            //...
    }
    class Object2Factory
        // Same implementation as Object1Factory
}

我正在尝试为我的应用程序提供一个例程,这个例程允许我调用适当的例程为我“新建”对象。

namespace MyApp
{
    class Program
    {
        static void Main()
            //...
        static Object getNewObject(string typeName)
        {
            //This is where I have problems
        }
    }
}

我可以访问外部库和我的程序的源代码,尽管整个架构的重写太昂贵了。

我尝试了什么: 我最初的想法是在工厂和/或工厂例程中使用自定义属性,并使用反射来获取方法,然后调用方法。我最初使用签名private static T getNew<T>()并尝试在type参数上使用switch语句,但实现getNewObject(string typeName)会更容易。工厂具有相同的构造函数签名,但没有继承链接。

总结:创建对象的例程在另一个程序集的工厂中,如何根据类型自动调用这些例程来获取对象?

3 个答案:

答案 0 :(得分:4)

如果您想继续沿着这条路走下去 - 您是否可以将所有工厂方法放在一个名为'ObjectFactory'的工厂类中?

Type t = typeof(OtherAssembly.ObjectFactory);

MethodInfo m = t.GetMethods().Where(a => a.ReturnType.Name == typeName).FirstOrDefault();

return m.Invoke(null, new object[] { /* PARAMETERS */ });


编辑 - 回应詹姆斯的问题评论,表示他更愿意将工厂课程分开:

(使用Martin的想法,并依赖于所有工厂类名称“[Type] Factory”)

(工厂类也有非静态方法)

Type t = Type.GetType(String.Format("OtherAssembly.{0}Factory", typeName));

var myFactory = Activator.CreateInstance( t );

MethodInfo m = t.GetMethods().Where(a => a.ReturnType.Name == typeName).FirstOrDefault();

return m.Invoke(myFactory, new object[] { /* PARAMETERS */ });

答案 1 :(得分:2)

也许我在问题中遗漏了一些东西,但是使用它时出了什么问题:

static Object getNewObject(string typeName)
{
    var type = Type.GetType(typeName);
    return Activator.CreateInstance(type);      
}

如果typeName是Object1并且您希望获得Object1Factory,然后使用反射来调用工厂上的getObject1()方法

,可能会进行一些字符串操作和反射

如果您可以传入typeName作为“MyNameSpace.Object1,Object1Assembly”,那么它将从相关程序集中加载它。

答案 2 :(得分:0)

纯粹是为了回应您的尝试,如果您将签名更改为:

static T GetNew<T>() where T : new()
{
    // Then you can do this:
    return new T();
}

它为类型T上的公共无参数构造函数设置了一个通用约束。但是,这是毫无意义的,因为调用代码看起来像这样:

var obj = GetNew<MyClass>();

然而它通常看起来像这样:

var obj = new MyClass();

所以我不会把它作为一个解决方案,但它会起作用,并且会否定对switch语句的需要。