1

我有一个这样的接口和类

public interface ICustomerEx
{
   void Load(DataRow row);
}

public class Customer:ICustomerEx
{
   public string Name{get;set;}
   public string Address{get;set;}

   void Load(DataRow row)
   {
    Name = (string)row["name"];
    Address = (string)row["address"];
   }
}

现在我将它构建为一个类库并添加到另一个项目作为参考。在那个项目中,有一个名为 UiCustomer 的类,它从相同的引用接口 ICustomerEx 实现。在这个类中,它有自己的属性并从其加载方法加载该属性。

public class UiCustomer:ICustomerEx
{
   public string Telephone{get;set;}

   void Load(DataRow row)
   {
    Telephone=(string)row["tele"];
   }
}

现在有什么方法可以实现我的第一个类(构建为类库)的加载方法,以在使用依赖注入加载它自己的属性后加载 Ui 项目的属性。

例如。

public class Customer:ICustomerEx
{
   public string Name{get;set;}
   public string Address{get;set;}

   void Load(DataRow row)
   {
    Name = (string)row["name"];
    Address = (string)row["address"];

    //Call load methods in other places that Interface implemented
   }
}
4

2 回答 2

2

这取决于你想要什么。像现在一样使用单独的类,您需要将 ICustomerEx 对象列表依赖注入到每个客户中,但最终会得到一堆不同的对象,每个对象都只有相关属性的一个子集. 听起来继承+模板方法模式可能更合适:

public class Customer:ICustomerEx
{
   public string Name{get;set;}
   public string Address{get;set;}

   void Load(DataRow row)
   {
       this.Name = (string)row["name"];
       this.Address = (string)row["address"];
       this.DoMoreLoading(row);
   }

   // this method is defined as a no-op in the base class, but it provides an extension point
   // for derived classes that want to load additional properties
   protected virtual void DoMoreLoading(DataRow row) { }
}

// note that now UiCustomer extends Customer (and thus still implements ICustomerEx
public class UiCustomer : Customer
{
   public string Telephone { get; set; }

   protected override void DoMoreLoading(DataRow row)
   {
       this.Telephone = (string)row["tele"];
   }
}

// usage
var uiCustomer = new UiCustomer();
uiCustomer.Load(row); // populates name, addr, and telephone

为了支持在库端实例化客户,您需要某种方式让库了解 UiCustomer 类。

一种方法是使用 IOC 容器注册 ICustomerEx,然后使用依赖注入解析实例:

// in the UI code (this is code for the Autofac IOC container):
ContainerBuilder cb = ...
cb.RegisterType<UiCustomer>().As<ICustomerEx>();
cb.RegisterType<AServiceThatNeedsACustomer>();

// in the library code
public class AServiceThatNeedsACustomer {
    private readonly ICustomerEx customer;
    // the customer will get injected by the IOC container
    public AServiceThatNeedsACustomer(ICustomerEx customer) {
        this.customer = customer;
    }
}

或者,您可以使用工厂模式:

// in the library:
public static class CustomerFactory {
   private static volatile Func<ICustomerEx> instance = () => new Customer(); 
   public static Func<ICustomerEx> Instance { get { return instance; } set { instance = value; } }        
}

// then to get a customer
var cust = CustomerFactor.Instance();
cust.Load(row);

// in the UI code:
CustomerFactory.Instance = () => new UiCustomer();
于 2013-07-06T13:20:46.713 回答
0

您可以像这样调用其他实现

在包含接口的程序集中,ICustomerEx您可以添加一个注册表类来存储这样的ICustomerEx实例

(注意这是伪代码,展示了它的运行方式。)

public class CustomerRegistry : ICustomerEx {
    // singelton
    public static final CustomerRegistry theRegistry = new CustomerRegistry();

    private ArrayList<ICustomerEx> customers = new ArrayList<ICustomerEx>();
    public void RegisterCustomer(ICustomerEx customer) {
       customers.add(customer);
    }

    public void Load(DataRow row)
    {
       foreach(ICustomerEx customer in customers) {
          customer.Load(row);
       }
    }
} 

ICustomerEx 的每个实现都需要调用注册表

CustomerRegistry.theRegistry.RegisterCustomer(new UiCustomer());

在您的主要客户类中,您使用注册表来调用其他负载

public class Customer:ICustomerEx
{
 void Load(DataRow row)
 {
   CustomerRegistry.theRegistry.Load(row);
 }
}
于 2013-07-06T14:08:33.927 回答