【问题标题】:Factory class returning a generic interface返回通用接口的工厂类
【发布时间】:2012-11-06 11:50:13
【问题描述】:

我很少有具体使用以下类型的接口

interface IActivity<T>
{
    bool Process(T inputInfo);
}

具体的类如下

class ReportActivityManager :IActivity<DataTable>
{
    public bool Process(DataTable inputInfo)
    {
        // Some coding here
    }
}

class AnalyzerActivityManager :IActivity<string[]>
{
    public bool Process(string[] inputInfo)
    {
        // Some coding here
    }
}

现在我该如何编写工厂类来重新调整通用接口,比如 IActivity。

class Factory
{
    public IActivity<T> Get(string module)
    {
        // ... How can i code here
    }
}

谢谢

【问题讨论】:

  • 出现错误..错误 CS0050:可访问性不一致:返回类型

标签: c# design-patterns generics factory


【解决方案1】:

您应该创建泛型方法,否则编译器将不知道返回值中T 的类型。当您拥有T 时,您将能够根据T 的类型创建活动:

class Factory
{
    public IActivity<T> GetActivity<T>()
    {
        Type type = typeof(T);
        if (type == typeof(DataTable))
            return (IActivity<T>)new ReportActivityManager();
        // etc
    }
}

用法:

IActivity<DataTable> activity = factory.GetActivity<DataTable>();

【讨论】:

  • 我收到一个错误“错误 CS0050:不一致的可访问性:返回类型”
  • 还无法将类型“Factory.ReportActivityManager”隐式转换为“Factory.IActivity”。存在显式转换(您是否缺少演员表?)
  • 它工作得很好..但是我想知道为什么当我将类设为公共时它的抛出和错误..抛出的错误是不一致的可访问性:返回类型 Factory.Managers.IActivityManager'比方法 'Factory.Managers.Factory.GetActivity()' 更难访问
  • @Anish 因为您的IActivity&lt;T&gt; 界面具有internal 可见性。你也应该公开它。
  • @Anish 欢迎 :) 顺便说一句,考虑使用依赖注入框架。例如。使用ninject,您可以像Bind&lt;IActivity&lt;DataTable&gt;&gt;().To&lt;ReportActivityManager&gt;(); 这样绑定您的经理,然后以这种方式检索实例:IActivity&lt;DataTable&gt; activity = kernel.Get&lt;IActivity&lt;DataTable&gt;&gt;();
【解决方案2】:

这通常在lazyberezovsky's answer 中实现。在 c++ 中,当您尝试创建工厂无法处理的类型时,您可以使用模板特化来获取编译器错误。

你不能在 C# 中做到这一点,但你可以接近。虽然代码可能看起来有点令人惊讶,这反过来可能是一个问题。

public static class Factory {
   public static IActivity<someType> Get(this someType self){
          //stuff specific to someType
   }

   public static IActivity<someOtherType> Get(someOtherType self){
          //stuff specific to someOtherType
   }

   public static T Creator<T>(){
        return null;
   }

}

那么用法就是

IActivity<someType> act = Factory.Creator<someType>().Get(); 

当然,这仅在您可以传递具体类型时才有效。如果您需要传递类型参数,事情会变得更加复杂。

【讨论】:

  • 我不太擅长 C#,但第二个不是扩展方法只是疏忽吗?
  • 另外,关于“当您尝试创建工厂无法处理的类型时,您可以使用模板专业化来获取编译器错误”,您不能在工厂运行时使用类型约束来获取编译器错误吗?递了一个不想处理的类型?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
相关资源
最近更新 更多