gpt4 book ai didi

c# - 这是对接口(interface)的错误使用吗?

转载 作者:行者123 更新时间:2023-11-30 23:24:27 25 4
gpt4 key购买 nike

以下面的例子为例,我有多个继承自同一个“IChannelIntegration”接口(interface)的“Integration”类。

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。 IntergrationFeature 接口(interface)是所有功能的来源。

public interface IIntegrationFeature {}

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

//Provides a concrete implementation of the logic.
public class CustomLogic : ICustomLogic
{
public void DoSomething() {}
}

然后创建了另一个接口(interface),该接口(interface)将附加到集成类以支持集成提供自定义功能。

public interface ISupportsFeature<T>  where T : Interfaces.IIntegrationFeature
{
T GetFeature();
}

将按如下方式实现;

public class IntegrationC : IChannelIntegration, ISupportsFeature<ICustomLogic>
{
public ICustomLogic GetFeature()
{
return new 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();
}
}

我不确定我对这个实现的看法,我的一部分认为我把情况复杂化了很多,但我也认为它很容易使用,因为我的许多集成都需要为其提供自定义逻辑。

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

最佳答案

我会从上到下,从您的需求到实现。

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

interface IIntegrationFeature {}

以及可以为您提供此功能的东西

interface IIntegratedSystem
{
T GetFeature<T>(string integrationType) where T : IIntegrationFeature;
}

此设置的客户端将使用这样的 actors

IIntegratedSystem system = .... // system implementation

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

if (feature != null)
{
//the feature exists and I'm using it
}

IIntegratedSystem实现的责任是提供 IIntegrationFeature来自现有的 IChannelIntegration实时选择或创建。您考虑过通知任何客户 IChannelIntegration实现通过实现 ISupportFeature<IIntegrationFeature> 实现了一个特性.当集成有大约 20 个功能时会发生什么?您将拥有一个实现集成接口(interface)本身的类和另外 20 个 ISupports接口(interface)。你如何添加另一个功能?您可以通过添加这个新的 ISupports<INewFeature> 来修改类违反单一职责原则。而且您不需要在编译时知道集成实现了某个功能,因为客户端可能会也可能不会使用它。基本上 IChannelIntegration听起来更像是集成的复合,应该能够提供 IIntegrationFeature因此 IChannelIntegration会有类似于 IIntegratedSystem 的定义

interface IChannelIntegration 
{
T GetFeature<T>() where T : IIntegrationFeature;
}

构建实现的方式 IChannelIntegration取决于你,但我更愿意在你的应用程序的根目录下创建功能。我的应该是这样的

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;
}
}

ChannelIntegration类维护功能列表。您使用 RegisterFeature要添加更多功能并确保是一个功能,您可以约束它们来实现 IIntegrationFeature界面。因此,当您添加新功能时,您不会更改 ChannelIntegration类,你用它。

IIntegratedSystem将从 IChannelIntegration 访问功能基于运行时值。正如您所说,这要求使用抽象工厂。这看起来像

interface IChannelIntegrationFactory 
{
IChannelIntegration CreateIntegration(string integrationType);
}

IIntegratedSystem将使用该工厂创建 IChannelIntegration为了实现这一点,我将使用构造函数注入(inject)机制。

   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;
}
}

现在 IntegratedSystem类正在使用 IChannelIntegrationFactory创建一个 IChannelIntegration基于运行时值,然后它将从中检索已实现的 IIntegrationFeature如果有的话。

我们现在需要的是实现这个将创建 IChannelIntegration 的工厂。与他们的 IIntegrationFeature

让我们先创建一个新功能

interface ICustomFeature : IIntegrationFeature {}

class CustomFeature : ICustomFeature
{
}

基于此抽象工厂实现就像

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以其单一的功能。当然你可以有多个路径,就像你开始创建不同的 IChannelIntegrations用自己的ICustomFeature s 并检索基于 integrationType 的那个参数。

那么你如何消费它?

    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.
}

您想添加新功能吗?在抽象工厂实现中注册它。

So would you expect to create a new abstract factory of type ChannelIntegrationFactory for each different type of ChannelIntegration?

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

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;
}
}

您甚至可以制作 ChannelIntegration作为抽象并创建专门的集成:

 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;
}
}

只需将此类视为系统的 Bootstrap 类即可。这是唯一创建与功能集成的类。顺便说一句,这就是您可以使用您喜欢的 IoC 轻松启用依赖倒置的方法。 Fiddle

关于c# - 这是对接口(interface)的错误使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37806663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com