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

时间:2013-07-06 11:54:07

标签: c# interface

我有一个像这样的接口和类

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实现 在这个类中,它有自己的属性,并从其load方法加载该属性。

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
   }
}

2 个答案:

答案 0 :(得分:2)

这取决于你想要什么。你现在使用单独的类,你需要依赖注入一个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();

答案 1 :(得分: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);
 }
}