动态类型传递和实例化 - 如何?

时间:2011-07-12 13:30:07

标签: c# dynamic

编辑:更改了Activator,仍然无效。

所以我对C#非常(非常)陌生,我很确定这是一个骗局,但我已经看过以前的问题而且我仍然无法解决所有问题。

我试图通过在通用列表上用地图替换一些重复的代码来减少代码气味。具体来说,我的代码看起来像

var fooNode = node as IFoo;
var barNode = node as IBar;
var bazNode = node as IBaz;
...

if(fooNode != null)
    return new FooThing();
if(barNode != null)
    return new BarThing();
if(bazNode != null)
    return new BazThing();
...

我想概括一下。


这是我的尝试:

var types = new Dictionary<Type, Type>
{
    {typeof(IFoo), typeof(FooThing)},
    {typeof(IBar), typeof(BarThing)},
    ...
}

foreach(var entry in types)
{
    var castNode = node as entry.Key;
    return Activator.CreateInstance(entry.Value);
}

当然,它不起作用:The type or namespace name 'entry' could not be found (are you missing a using directive or an assembly reference?)。你能帮我吗?这种事情在C#中是否可能?

3 个答案:

答案 0 :(得分:3)

这个怎么样?

foreach(var entry in types)
{
    if (node != null && entry.Key.IsAssignableFrom(node.GetType()))
    {
        return Activator.CreateInstance(entry.Value);
    }
}

问题在于您将泛型类型参数与运行时类型混淆,尤其是Type类。

如果您知道编译时类型是什么,那么您可以使用通用Activator.CreateInstance<T>()方法创建基础对象的实例 - 您可以使用类型参数之类的东西,这样代码行就可以了我需要知道类型是什么,例如:

T CreateObject<T>()
{
    return Activator.CreateInstance<T>();
}

然而,这只是推卸责任。为了调用此方法,必须在某处提供类型参数T的值 - 无论是哪种方式,编译器都必须能够将T解析为类型(而不是变量或方法)。

相反,Type类对运行时中的类型信息进行编码,例如其名称或声明类型的程序集。Activator.CreateInstance还附带一个允许您的重载提供Type的实例:

object CreateObject(Type type)
{
    return Activator.CreateInstance(type);
}

在你的情况下,看起来你不知道在编译时类型是什么,因此你将主要使用Type类 - 你可以使用typeof(MyClass)来获取一个实例对于在运行时已知的类的相应Type,以及myObject.GetType()在运行时获取对象的类型信息。

答案 1 :(得分:2)

var types = new Dictionary<Type, Type>
{
    {typeof(IFoo), typeof(FooThing)},
    {typeof(IBar), typeof(BarThing)},
    ...
}

foreach(var entry in types)
{
    if(entry.Key.IsAssignableFrom(node.GetType()))
       return Activator.CreateInstance(entry.Value);
}

return null;

答案 2 :(得分:0)

如果不清楚你想要从同一操作中返回不同类型的目的,那将很难提供帮助。也许有一些背景信息可以解决你想要解决的问题?

我会假设,因为你试图互换它们,fooThing,BartThing和BazThing具有相同的界面。所以我假设以下内容:

 public class FooThing : IMyOperations
 {

 }

 public class BarThing : IMyOperations
 {

 }

 public class BazThing : IMyOperations
 {

 }

您可以在另一个界面中定义类之间的关系

 public interface IMyChoice
 {
      public bool IsSelected { get; }
      public IMyOperations GetWorker();
 } 

 public class ChoiceFoo : IMyChoice
 {


 }

 public class ChoiceBar : IMyChoice
 {

 }

 public class ChoiceBaz : IMyChoice
 {

 }

现在你可以说

 foreach( var entry in choices)
 {
    if(entry.IsSelected)
    {
         return entry.GetWorker();
         //Can't remember if i need to break after return..doubt it
    }
 }