C# 这个图案有名字吗

C# 这个图案有名字吗,c#,generics,design-patterns,integration-patterns,C#,Generics,Design Patterns,Integration Patterns,我已经在很多地方多次使用过这个模式,通常是在插件模式旁边 我使用它的一些示例方法用于消息传递系统,例如为各种类型的无关消息创建订户。我还将其用于通用集成工作流,每个工作流都需要不同形状的上下文对象 基本上,该模式包括为消息或上下文定义空白标记接口。然后定义一个与消息/上下文接口一起工作的高级工作流接口。然后可以使用工厂获取工作流的具体实例,如果需要,工作流还可以负责从通用数据格式解析其消息/上下文 接下来,您将创建一个抽象的通用基本工作流,其职责只是将对接口方法的调用映射到对抽象方法的调用中,这

我已经在很多地方多次使用过这个模式,通常是在插件模式旁边

我使用它的一些示例方法用于消息传递系统,例如为各种类型的无关消息创建订户。我还将其用于通用集成工作流,每个工作流都需要不同形状的上下文对象

基本上,该模式包括为消息或上下文定义空白标记接口。然后定义一个与消息/上下文接口一起工作的高级工作流接口。然后可以使用工厂获取工作流的具体实例,如果需要,工作流还可以负责从通用数据格式解析其消息/上下文

接下来,您将创建一个抽象的通用基本工作流,其职责只是将对接口方法的调用映射到对抽象方法的调用中,这些方法在无用的标记接口周围传递,这些抽象方法采用消息/上下文的具体版本

希望这是有道理的。我将在下面提供一个代码示例。我很想知道这个图案是否有名字,因为我注意到我现在已经用了大约4-5次了。另外,我正在充实如何解释这个模式,所以如果我的解释有任何不合理之处,也请让我知道

要点是,您可以拥有多个具有不同方法签名的类,这些类仍然可以通过公共接口调用:

最终结果

public class ConcreteA : Base<MessageA>
{
    public void Process(MessageA message){...}
    public MessageA Parse(IDictionary data){...}
}

public class ConcreteB : Base<MessageB>
{
    public void Process(MessageB message){...}
    public MessageB Parse(IDictionary data){...}
}

//And both can by called by...
public void Main(){
    var data = GetDataFromIntegrationSource(someContext);
    IWorkflow impl = Factory.GetConcrete(someContext);

    //So in your classes you're able to work with strongly typed parameters,
    //But in the consuming code you still can use a common interface
    //Consuming code never even knows what the strong type is. 
    IMessage msg = impl.Parse(data);
    impl.Process(msg);
}
具体实施

public class SomeRandomlyShapedMessageOrContext : IGenericeMarkerInterface
{
    public int ID { get; set; }
    public string Data { get; set; }
}

[MappingAttributeUsedByFactory(WorkflowType.IntegrationPartnerB)]
public class ConcreteWorkflow : GenericWorkflowBase<SomeRandomlyShapedMessageOrContext>
{
    public override void Process(SomeRandomlyShapedMessageOrContext messageOrContext)
    {
        //TODO: process the strongly typed message
    }

    public override SomeRandomlyShapedMessageOrContext DoParse(IDictionary<string, string> commonDataFormat)
    {
        //TODO: parse the common data into the strongly typed message            
    }
}
示例用法

public static class Program
{
    public static void Main(string[] args)
    {
        //this could be driven by a UI or some contextual data
        var someSortOfWorkflowIdentifier = (WorkflowType)args[0];
        var data = GetSomeDictionaryOfData();

        var workflow = WorkflowFactory.Get(someSortOfWorkflowIdentifier);

        workflow.Process(workflow.Parse(data));
    }
}

是的,它与您命名的完全相同:

C#支持属性。@HansPassant和Java也支持属性。我称之为糟糕的设计气味模式。你不是在做正确的面向对象编程,而是在用泛型进行黑客攻击。@Euphoric你会有什么不同吗?@HansPassant如果元数据需要在运行时更改,接口就很好了。特别是如果元数据的一部分需要本地化,其他人是否同意这一点?在我接受之前,我想确定一下。我知道我用作为泛型参数标准的空接口是一个标记接口,但它似乎不仅仅是一个模式。就像使用抽象泛型库将标记接口映射到具体类型,然后使用接受不同类型参数但仍可通过单个公共接口调用的方法创建具体实现。另一件事是,有时它甚至不是标记接口,有时,您有一个带有公共字段的基本消息或上下文类,但模式的其余部分保持不变,即设置类型无关接口,然后在其下面设置一个泛型基。
public class MappingAttributeUsedByFactoryAttribute : Attribute
{
    public WorkflowType SomePropertyForMapping { get; set; }
}
public class SomeRandomlyShapedMessageOrContext : IGenericeMarkerInterface
{
    public int ID { get; set; }
    public string Data { get; set; }
}

[MappingAttributeUsedByFactory(WorkflowType.IntegrationPartnerB)]
public class ConcreteWorkflow : GenericWorkflowBase<SomeRandomlyShapedMessageOrContext>
{
    public override void Process(SomeRandomlyShapedMessageOrContext messageOrContext)
    {
        //TODO: process the strongly typed message
    }

    public override SomeRandomlyShapedMessageOrContext DoParse(IDictionary<string, string> commonDataFormat)
    {
        //TODO: parse the common data into the strongly typed message            
    }
}
public static class WorkflowFactory
{
    public static IGenericWorkflow Get(WorkflowType workflow) 
    {
        //TODO: find the concrete workflow by inspecting attributes
    }
}
public static class Program
{
    public static void Main(string[] args)
    {
        //this could be driven by a UI or some contextual data
        var someSortOfWorkflowIdentifier = (WorkflowType)args[0];
        var data = GetSomeDictionaryOfData();

        var workflow = WorkflowFactory.Get(someSortOfWorkflowIdentifier);

        workflow.Process(workflow.Parse(data));
    }
}