在不同的程序集中实现接口

本文关键字:集中 实现 接口 程序集 程序 | 更新日期: 2023-09-27 18:21:12

我有一个类似的接口和类

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

现在有没有任何方法可以实现我的第一个类(作为类库构建)的Load方法,在使用类似依赖注入的方法加载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
   }
}

在不同的程序集中实现接口

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

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();

您可以调用其他类似的实现

在包含接口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);
 }
}