C# 这是对接口的错误使用吗?

C# 这是对接口的错误使用吗?,c#,interface,factory,C#,Interface,Factory,以下面的示例为例,我有多个“集成”类,它们继承自同一个“IChannelIntegration”接口 public interface IChannelIntegration { } public class IntegrationA : IChannelIntegration { } public class IntegrationB : IChannelIntegration { } public IChannelIntegration CreateIntegration(str

以下面的示例为例,我有多个“集成”类,它们继承自同一个“IChannelIntegration”接口

public interface IChannelIntegration
{

}

public class IntegrationA : IChannelIntegration
{

}

public class IntegrationB : IChannelIntegration
{

}

public IChannelIntegration CreateIntegration(string letter)
{
   if(letter = "A")
   {
     return new IntegrationA();
   }
   else if (letter = "B")
   {
     return new IntegrationB();
   }
   else
   {
     return null;
   }
}
我的一个集成提供了一些其他集成所没有的功能。我需要一种对CreateIntegration函数返回的IChannelIntegration对象调用此功能的方法

我创建了以下用于处理这些定制IntegrationFeatures的类集合。IntegrationFeature接口是所有功能的来源

public interface IIntegrationFeature {}

public interface ICustomLogic : IIntegrationFeature 
{
  void DoSomething() {}
} 

//Provides a concrete implementation of the logic.
public class CustomLogic : ICustomLogic 
{
  public void DoSomething() {}
}
然后创建了另一个接口,该接口将附加到集成类,以支持集成提供自定义功能

public interface ISupportsFeature<T>  where T : Interfaces.IIntegrationFeature
{
    T GetFeature();
}
公共接口iSupports功能,其中T:Interfaces.IIntegrationFeature
{
T GetFeature();
}
它将按以下方式实施

public class IntegrationC : IChannelIntegration, ISupportsFeature<ICustomLogic>
{
    public ICustomLogic GetFeature()
    {
        return new CustomLogic ();
    }
}
公共类集成C:IChannelIntegration,ISupportsFeature
{
公共ICustomLogic GetFeature()
{
返回新的CustomLogic();
}
}
这就是你给集成的方法,它是特定的逻辑,然后你可以用下面的方法来调用它

public static IIntegrationFeature GetIntegrationFeature<IIntegrationFeature>()
        where IIntegrationFeature : Interfaces.IIntegrationFeature
    {
        IIntegrationFeature integrationFeature = null;

        IChannelIntegration service = CreateIntegration();

        //Attempt to cast the integration too determine if it supports the Integration Feature.
        ISupportsFeature<IIntegrationFeature> supportsFeature = service as ISupportsFeature<IIntegrationFeature>;

        if(supportsFeature != null)
        {
            integrationFeature = supportsFeature.GetFeature();
        }

        return integrationFeature;
    }

public void TestMethod()
{
    ICustomLogic customLogic = GetIntegrationFeature<ICustomLogic>();
    if (customLogic != null)
    {
        customLogic.DoSomething();
    }
}
public静态集成功能GetIntegrationFeature()
其中IIintegrationFeature:Interfaces.IIintegrationFeature
{
IIintegrationFeature integrationFeature=null;
IChannelIntegration服务=CreateIntegration();
//尝试强制转换集成以确定它是否支持集成功能。
iSupportsFeatureSupportsFeature=作为ISupportsFeature的服务;
如果(supportsFeature!=null)
{
integrationFeature=supportsFeature.GetFeature();
}
返回积分特征;
}
公共void TestMethod()
{
ICustomLogic customLogic=GetIntegrationFeature();
if(customLogic!=null)
{
customLogic.DoSomething();
}
}
我不确定我对这个实现的感觉如何,我的一部分人认为我的情况过于复杂,但我也认为它很容易使用,因为我的许多集成需要为它们提供自定义逻辑


另一个问题是,如果一个集成提供了多个IntegrationFeatures,您将不得不显式调用接口函数,因为它们具有相同的GetFeature名称,这可能会给其他开发人员带来更多混乱。

我将从上到下,从您的需要到实现

据我所见,您需要在运行时访问由特定系统根据给定值创建的集成所提供的功能。所以你的第一个演员是

interface IIntegrationFeature {}
还有一些东西可以为你提供这个功能

interface IIntegratedSystem
{
  T GetFeature<T>(string integrationType) where T : IIntegrationFeature;
}
构建实现的方式取决于您,但我更喜欢在应用程序的根目录上创建特性。我的是这样的

IIntegratedSystem system = .... // system implementation

T feature = system.GetFeature<T>("Which integration type?");

if (feature != null)
{
    //the feature exists and I'm using it
}
class ChannelIntegration : IChannelIntegration
{
    private Dictionary<Type, IIntegrationFeature> features;
    public ChannelIntegration()
    {
        features = new Dictionary<Type, IIntegrationFeature>();
    }
    public void RegisterFeature<T>(IIntegrationFeature feature) where T:IIntegrationFeature
    {
        features.Add(typeof(T), feature);
    }
    public T GetFeature<T>() where T : IIntegrationFeature
    {
        IIntegrationFeature feature = features.TryGetValue(typeof(T), out feature) ? feature : null;
        return (T)feature;
    }
}
IIntegratedSystem
将使用此工厂创建
IChannelIntegration
,为此,我将使用构造函数注入机制

   class IntegratedSystem : IIntegratedSystem
{
    private IChannelIntegrationFactory integrationFactory;
    public IntegratedSystem(IChannelIntegrationFactory integrationFactory)
    {
        this.integrationFactory = integrationFactory;
    }
    public T GetFeature<T>(string integrationType) where T: IIntegrationFeature
    {
        T integrationFeature = default(T);
        IChannelIntegration integration = integrationFactory.CreateIntegration(integrationType);
        if (integration != null)
        {
            integrationFeature = (T)integration.GetFeature<T>();    
        }
        return integrationFeature;
    }
}
基于此,抽象工厂实现如下

class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        // use integrationType to decide witch IChannelIntegration to use
        IChannelIntegration integration = new ChannelIntegration();
        integration.RegisterFeature<ICustomFeature>(new CustomFeature());

        return integration;
    }
}
是否要添加新功能?在抽象工厂实现中注册它

那么您希望为每种不同类型的ChannelIntegration创建一个新的ChannelIntegrationFactory类型的抽象工厂吗?

不是。工厂从具体实现列表中选择一个。这里有一个例子

class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        IChannelIntegration integration = null;
        switch (integrationType)
        {
            case "MobileIntegration":
                integration = new ChannelIntegration();
                integration.Register<ITapGestureTrack>(new TapGestureTrack());
                break;
            case "DesktopIntegration":
                integration = new ChannelIntegration();
                integration.Register<IClickTrack>(new ClickTracker());
                integration.Register<ILargeImagesProvider>(new LargeImagesProvider());
                break;
        }
        return integration;
    }
}
抽象工厂变成了

class ChannelIntegrationFactory : IChannelIntegrationFactory
    {
        public IChannelIntegration CreateIntegration(string integrationType)
        {
            IChannelIntegration integration = null;
            switch (integrationType)
            {
                case "MobileIntegration":
                    integration = new MobileIntegration();
                    break;
                case "DesktopIntegration":
                    integration = new DesktopIntegration();
                    break;
            }
            return integration;
        }
    }
只需将该类视为系统的引导类。这是唯一一个创建与功能集成的类。顺便说一句,这就是使用首选IoC轻松启用依赖项反转的方法。

我投票结束这个问题,因为OP要求进行代码审查。代码正常工作,没有具体问题需要解决。很抱歉,我不知道有一个代码审查部分。@Eritey:see:我认为这
公共类ICCustomLogic:IIintegrationFeature{void DoSomething(){}}
是一个接口而不是类,这不是关于代码审查(不要张贴在那里),而是关于设计。也许对程序员来说是这样,但我不会投票来结束这个。我曾经考虑过这样做,但没有找到一个好的方法告诉ChannelIntegration它支持什么功能。那么,您希望为每种不同类型的ChannelIntegration创建一个新的ChannelIntegrationFactory类型的抽象工厂吗?您的示例非常清晰,经过深思熟虑,非常感谢。我想我更喜欢在构造函数中添加功能的第二种解决方案,我们有超过15个集成,因此在单个类中管理它们可能会变得相当混乱。国际奥委会也代表什么?我以前没有看到过这一点。请参阅依赖项反转和控制反转之类的主题。如果您创建了这么多不同类型的对象,这似乎是一个很好的候选对象。
class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        // use integrationType to decide witch IChannelIntegration to use
        IChannelIntegration integration = new ChannelIntegration();
        integration.RegisterFeature<ICustomFeature>(new CustomFeature());

        return integration;
    }
}
    IIntegratedSystem system = new IntegratedSystem(new ChannelIntegrationFactory());
    ICustomFeature customFeature = system.GetFeature<ICustomFeature>("Which Integration?");
    if (customFeature != null)
    {
        //use this custom feature

    }
    else
    {
        // that's OK, will wait until is registered.
    }
class ChannelIntegrationFactory : IChannelIntegrationFactory
{
    public IChannelIntegration CreateIntegration(string integrationType)
    {
        IChannelIntegration integration = null;
        switch (integrationType)
        {
            case "MobileIntegration":
                integration = new ChannelIntegration();
                integration.Register<ITapGestureTrack>(new TapGestureTrack());
                break;
            case "DesktopIntegration":
                integration = new ChannelIntegration();
                integration.Register<IClickTrack>(new ClickTracker());
                integration.Register<ILargeImagesProvider>(new LargeImagesProvider());
                break;
        }
        return integration;
    }
}
 class MobileIntegration : ChannelIntegration
    {
       public MobileIntegration()
       {
            Register<ITapGestureTrack>(new TapGestureTrack());
       }
    }

    class DesktopIntegration : ChannelIntegration
    {
       public DesktopIntegration()
       {
            Register<IClickTrack>(new ClickTracker());
            Register<ILargeImagesProvider>(new LargeImagesProvider());
       }
    }
class ChannelIntegrationFactory : IChannelIntegrationFactory
    {
        public IChannelIntegration CreateIntegration(string integrationType)
        {
            IChannelIntegration integration = null;
            switch (integrationType)
            {
                case "MobileIntegration":
                    integration = new MobileIntegration();
                    break;
                case "DesktopIntegration":
                    integration = new DesktopIntegration();
                    break;
            }
            return integration;
        }
    }