实例化类型与字符串参数构造器,动态

问题描述:

我有以下代码:实例化类型与字符串参数构造器,动态

if (FileType == typeof(ScanUploadFile)) 
{ 
    files.Add(new ScanUploadFile(filePath)); 
} 
if (FileType == typeof(FaxFile)) 
{ 
    files.Add(new FaxFile(filePath)); 
} 
if (FileType == typeof(BulkScanFile)) 
{ 
    files.Add(new BulkScanFile(filePath)); 
} 
if (FileType == typeof(SpecialCategoryFile)) 
{ 
    files.Add(new SpecialCategoryFile(filePath)); 
} 

我怎样才能把它写不IF语句?

由于您只对构造函数感兴趣,所以可以使用:

Activator.CreateInstance(FileType, new string[] {filePath}); 

ActivatorSystem库中定义。

+0

goog一个,我忘了'CreateInstance'具有参数 – Dyppl 2011-03-17 05:19:37

+0

我用它在对象映射库一次过载。 :) – neontapir 2011-03-17 05:20:37

+0

我用它,但我的最新项目,我想检查类型是否实际上有我需要的构造。这是使用'CreateInstance'的缺点 - 你有点希望正确的构造函数存在。在某些情况下,你无法确切地知道,并且突然间你正在做一些类似“异常编程”的事情,这很糟糕。 – Dyppl 2011-03-17 05:25:40

使用Type对象的GetConstructors方法和选择的一个类型为字符串的单个参数,则调用它。

像这样:

private ConstructorInfo GetStringConstructor(Type type) 
{ 
    return (from ctor in type.GetConstructors() 
      let pars = ctor.GetParameters() 
      where pars.Length == 1 && pars[0].ParameterType == typeof(string) 
      select ctor).FirstOrDefault(); 
} 

使用它,像这样:

var ctor = GetStringConstructor(typeof(Test)); 
if (ctor != null) 
    files.Add(ctor.Invoke(new string[] {filePath})); 

我做了一个单独的方法提取的构造,但如果你只打算使用它实际上是创建一个实例,你可以重构它在同一个方法,它stringType参数。尽管如此,请注意正确的错误处理。

但是,我会在这里考虑Factory method pattern,而不是只是在反射中立即潜水。我不知道它是否更适合您的需求,但似乎可能。

编辑:有人问津解释downvotes?我承认CreateInstance更好,但我的方法具有更多的控制和更好的错误处理优势,所以我认为它至少应该在这里展示

+0

我有反射的工作 - 谢谢。如果我使用工厂模式,我不会将IF语句移入工厂吗?我想工厂会像FileFactory一样,用一个名为GetFile(Type fileType,string filePath)的方法和我的问题中的IF语句。 – Anthony 2011-03-17 05:08:25

+0

@Anthony:是的,但是然后交换机(或ifs)只会在一个地方(创建方法)。当你只需要改变一次以添加新类型时,这并不是什么大不了的事情。另外,反射并不便宜。我并不是说你必须过早地优化这样的东西,但反射也不会更易读,而ifs的即时处理会在编译时给你错误,而不是在运行时出错(没有找到合适的构造函数) )。底线是,即使您在创建方法中使用了反射,您也应该将其封装在类似工厂的东西中。 – Dyppl 2011-03-17 05:15:01