c#模式的帮助

c#模式的帮助,c#,.net,oop,design-patterns,architecture,C#,.net,Oop,Design Patterns,Architecture,你好,谢谢你的帮助 使用.Net 3.5 C# 假设我有大约10种方法都遵循相同的模式 以3为例: public Customer CreateCustomer(Customer c) { .. } public Car CreateCar(Car c) { .. } public Planet CreatePlanet(Planet p) { ..} 每个方法的内部逻辑都有完全相同的模式 即: CreatePlanet和其他7种方法也是如此 这些方法可以重新编写吗?它们都遵循相同的模式,我觉

你好,谢谢你的帮助

使用.Net 3.5 C#

假设我有大约10种方法都遵循相同的模式

以3为例:

public Customer CreateCustomer(Customer c) { .. }
public Car CreateCar(Car c) { .. }
public Planet CreatePlanet(Planet p) { ..}
每个方法的内部逻辑都有完全相同的模式

即:

CreatePlanet和其他7种方法也是如此

这些方法可以重新编写吗?它们都遵循相同的模式,我觉得我遗漏了一些东西。。。是否存在可以派生的另一个抽象级别

问题:应该如何重新编写以利用适当的架构模式

谢谢,
Steven

这似乎是一个符合模板模式的案例。您可以使所有实体实现相同的接口/基础,并对接口执行操作

我假设唯一需要知道实际类型的部分是
Validate()
。这可以通过两种方式解决:

  • 让接口/基声明验证,然后在每个具体实体中实现它
  • 定义具体实体类型和实际验证策略之间的策略映射
  • 使用基类抽象验证的示例-

    实体的基础,其中有用于创建的内部服务和用于验证的抽象定义:

    public abstract class EntityBase
    {
        protected abstract void Validate();
    
        protected void Create(EntityBase c)
        {
            Log.BeginRequest(c, ActionType.Create);
            c.Validate();
            WebService.Send(Convert(c));
            Log.EndRequest(c, ActionType.Create); 
        }
    }
    
    具有验证功能的具体实施者:

    public class Customer : EntityBase
    {
        private int year;
    
        public Customer(int year)
        {
            this.year = year;
        }
    
        public void CreateCustomer(Customer c)
        {
            Create(c);
        }
    
        protected override void Validate()
        {
            if (year < 1900)
            {
                throw new Exception("Too old");
            }
        }
    }
    
    公共类客户:EntityBase
    {
    私人国际年;
    公共客户(国际年)
    {
    今年=年;
    }
    公共客户(客户c)
    {
    创建(c);
    }
    受保护的覆盖无效验证()
    {
    如果(年份<1900年)
    {
    抛出新异常(“太旧”);
    }
    }
    }
    

    我在原始代码中没有看到
    Create
    返回的内容,因此我将其更改为void,以使示例更加清晰

    它似乎符合模板模式。您可以使所有实体实现相同的接口/基础,并对接口执行操作

    我假设唯一需要知道实际类型的部分是
    Validate()
    。这可以通过两种方式解决:

  • 让接口/基声明验证,然后在每个具体实体中实现它
  • 定义具体实体类型和实际验证策略之间的策略映射
  • 使用基类抽象验证的示例-

    实体的基础,其中有用于创建的内部服务和用于验证的抽象定义:

    public abstract class EntityBase
    {
        protected abstract void Validate();
    
        protected void Create(EntityBase c)
        {
            Log.BeginRequest(c, ActionType.Create);
            c.Validate();
            WebService.Send(Convert(c));
            Log.EndRequest(c, ActionType.Create); 
        }
    }
    
    具有验证功能的具体实施者:

    public class Customer : EntityBase
    {
        private int year;
    
        public Customer(int year)
        {
            this.year = year;
        }
    
        public void CreateCustomer(Customer c)
        {
            Create(c);
        }
    
        protected override void Validate()
        {
            if (year < 1900)
            {
                throw new Exception("Too old");
            }
        }
    }
    
    公共类客户:EntityBase
    {
    私人国际年;
    公共客户(国际年)
    {
    今年=年;
    }
    公共客户(客户c)
    {
    创建(c);
    }
    受保护的覆盖无效验证()
    {
    如果(年份<1900年)
    {
    抛出新异常(“太旧”);
    }
    }
    }
    

    我在原始代码中没有看到
    Create
    返回的内容,因此我将其更改为void,以使示例更加清晰

    我认为您正在寻找解决方案

    public T Create<T>(T t)
    {
        Log.BeginRequest(t, ActionType.Create); 
        Validate(t);
        WebService.Send(Convert(t));
        Log.EndRequest(t, ActionType.Create);
        return t;
    }
    
    public T创建(T T)
    {
    Log.BeginRequest(t,ActionType.Create);
    验证(t);
    Send(Convert(t));
    EndRequest(t,ActionType.Create);
    返回t;
    }
    
    我认为您正在寻找解决方案

    public T Create<T>(T t)
    {
        Log.BeginRequest(t, ActionType.Create); 
        Validate(t);
        WebService.Send(Convert(t));
        Log.EndRequest(t, ActionType.Create);
        return t;
    }
    
    public T创建(T T)
    {
    Log.BeginRequest(t,ActionType.Create);
    验证(t);
    Send(Convert(t));
    EndRequest(t,ActionType.Create);
    返回t;
    }
    
    您可以使用通用方法:

    T Create<T>(T arg)
    

    您可以使用一般方法:

    T Create<T>(T arg)
    

    如果只有类型不同或可以创建泛型方法,则可以为这十种类型提取公共接口。

    如果只有类型不同或可以创建泛型方法,则可以为这十种类型提取公共接口。

    是,使用泛型函数:

      public T TrackInstantiation<T>(T entity)
      {
        Log.BeginRequest(entity, ActionType.Create); 
        Validate(entity);
        WebService.Send(Convert(entity));
        Log.EndRequest(entity, ActionType.Create);
        // Don't you also need to return the thing to fulfill the method siugnature ?
        return entity;
      }
    

    。。。并对上述方法调用的三个方法中的每一个方法进行重载,输入参数类型为ICanBeTracked reference

    Yes,带有泛型函数:

      public T TrackInstantiation<T>(T entity)
      {
        Log.BeginRequest(entity, ActionType.Create); 
        Validate(entity);
        WebService.Send(Convert(entity));
        Log.EndRequest(entity, ActionType.Create);
        // Don't you also need to return the thing to fulfill the method siugnature ?
        return entity;
      }
    
     public T Create<T>(T c)
     {
        Log.BeginRequest(c, ActionType.Create); 
        Validate(customer);
        WebService.Send(Convert(c));
        Log.EndRequest(c, ActionType.Create); 
     }
    
    。。。并为上述方法调用的三个方法中的每一个方法创建一个重载,输入参数键入为ICanBeTracked reference

    public T Create(tc)
    
     public T Create<T>(T c)
     {
        Log.BeginRequest(c, ActionType.Create); 
        Validate(customer);
        WebService.Send(Convert(c));
        Log.EndRequest(c, ActionType.Create); 
     }
    
    { Log.BeginRequest(c,ActionType.Create); 验证(客户); Send(Convert(c)); EndRequest(c,ActionType.Create); }
    公共T创建(T c)
    {
    Log.BeginRequest(c,ActionType.Create);
    验证(客户);
    Send(Convert(c));
    EndRequest(c,ActionType.Create);
    }
    
    我看到了一些关于模板函数的建议。这很好,但不能说明全部情况。我猜问题的一部分在于,每个Validate和Convert函数的工作方式略有不同,这意味着一个简单的泛型函数可能不够

    如果是这样,你有几个选择。一种是重载Validate/Convert函数,让类型系统的重载解析计算出要调用哪个函数。另一种方法(这是首选方法)是使用前面推荐的模板模式,让每个类型实现一个公共接口。第三个选项是为每个方法的函数要求一个委托参数。您已经有了前两个示例,下面是一个代码示例,介绍如何编写方法来接受委托:

    public T Create<T>(T c, Action<T> validate, Func<T, string> convert)
    {
        Log.BeginRequest(c, ActionType.Create);
    
        validate(c);
        WebService.Send(convert(c));
    
        Log.EndRequest(c, ActionType.Create);
    }
    
    publictcreate(tc、动作验证、函数转换)
    {
    Log.BeginRequest(c,ActionType.Create);
    验证(c);
    Send(convert(c));
    EndRequest(c,ActionType.Create);
    }
    
    我看到了一些关于模板函数的建议。这很好,但不能说明全部情况。我猜问题的一部分在于,每个Validate和Convert函数的工作方式略有不同,这意味着一个简单的泛型函数可能不够

    如果是这样,你有几个选择。一是让Va过载