1

我正在尝试在我的程序中创建一个通用例程,它将为我实例化对象。实际负责调用 new 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>()并尝试在类型参数上使用 switch 语句,但实现起来getNewObject(string typeName)会更容易。工厂具有相同的构造函数签名,但没有继承链接。

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

4

3 回答 3

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 的想法,并依赖于所有 Factory 类的名称为“[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 */ });
于 2012-05-23T15:34:34.433 回答
2

也许我在问题中遗漏了一些东西,但是仅仅使用这个有什么问题:

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

如果 typeName 是 Object1 并且您想获取 Object1Factory,则可能需要进行一些字符串操作和反射,然后使用反射调用工厂上的 getObject1() 方法

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

于 2012-05-23T15:28:40.807 回答
0

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

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

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

var obj = GetNew<MyClass>();

而它通常看起来像这样:

var obj = new MyClass();

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

于 2012-05-23T15:23:37.517 回答