帮助c#模式

时间:2009-11-28 16:56:58

标签: c# architecture oop design-patterns

您好,感谢您的帮助。

使用.Net 3.5 C#;

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

以3为例:

public Customer CreateCustomer(Customer c) { .. }
public Car CreateCar(Car c) { .. }
public Planet CreatePlanet(Planet p) { ..}

每种方法的内部逻辑具有完全相同的模式。

IE:

public Customer CreateCustomer(Customer c)
{
Log.BeginRequest(c, ActionType.Create); 
Validate(customer);
WebService.Send(Convert(c));
Log.EndRequest(c, ActionType.Create); 
}

public Car CreateCar(Car c)
{
Log.BeginRequest(c, ActionType.Create); 

Validate(c);

WebService.Send(Convert(c));

Log.EndRequest(c, ActionType.Create); 
}

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

这些方法可以重写,它们都遵循相同的模式,我觉得我错过了一些东西......是否有另一层抽象可以衍生出来?

问题:如何重写以利用适当的架构模式?

谢谢, 史蒂文

8 个答案:

答案 0 :(得分:7)

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

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

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

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

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

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

答案 1 :(得分:2)

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

public T Create<T>(T t)
{
    Log.BeginRequest(t, ActionType.Create); 
    Validate(t);
    WebService.Send(Convert(t));
    Log.EndRequest(t, ActionType.Create);
    return t;
}

答案 2 :(得分:1)

是的,使用通用功能:

  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 interface ICanBeTracked {/ * No methods * /}

修改要传递给此方法的每个类型,以便它们也实现此接口,然后只需编写方法

  public ICanBeTracked TrackInstantiation(ICanBeTracked  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参考

对上述方法调用的三种方法中的每一种进行重载

答案 3 :(得分:1)

 public T Create<T>(T c)
 {
    Log.BeginRequest(c, ActionType.Create); 
    Validate(customer);
    WebService.Send(Convert(c));
    Log.EndRequest(c, ActionType.Create); 
 }

答案 4 :(得分:0)

您可以使用通用方法:

T Create<T>(T arg)

或者只是System.Object:

object Create(object arg);
{
   Log.BeginRequest(arg, ActionType.Create); 
   Validate(arg);
   WebService.Send(Convert(arg));
   Log.EndRequest(arg, ActionType.Create); 
   return arg; //It must have a return
}

Car CreateCar(Car c)
{
   return (Car)Create(c);
}

答案 5 :(得分:0)

如果类型不同或者您可以创建通用方法,则可以为这十种类型提取公共接口。

答案 6 :(得分:0)

我看到了一些模板功能的建议。这很好,但它并不能说明整个故事。我猜测问题的一部分是你的每一个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);
}

答案 7 :(得分:0)

您可以使用面向方面的编程来应用日志记录和验证。使用来自Microsoft Patterns&amp; Sons的PIAB(策略注入应用程序块)(企业库的一部分)。实践团队(假设配置已经到位)你最终会得到这样的结论:

[LogRequest(ActionType.Create)]
[DoValidate()]
public T Create<T>(T item)
{
   WebService.Send(convert(item));
}

其中LogRequest是一个自定义属性,用于实例化新的ICallHandler,在其中记录请求的开始,调用getNext()(将控制权发送到链中的下一个ICallHandler,或者如果这是最后一个链,将控制发送到被调用的方法),然后当控制返回到ICallHandler时,它将记录请求的结束。

验证可能由验证应用程序块处理,该块与PIAB无缝协作 或者你可以编写自己的验证处理程序

AOP可以大幅减少您需要的代码量,但请注意不要过度使用它。

您可以在此处阅读企业库:http://www.codeplex.com/entlib/