简体   繁体   English

在不同程序集中实现接口

[英]Implementing interface in different assemblies

I have an interface and class like this 我有这样的接口和类

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

Now I'm building this as a class library and add to another project as a reference. 现在,我将其构建为类库,并添加到另一个项目中作为参考。 In that project there's a class called UiCustomer that implements from the same refereced interface ICustomerEx In this class it has its own property and load that property from its load method. 在该项目中,有一个称为UiCustomer的类,它从相同的引用接口ICustomerEx实现。在该类中,它具有自己的属性,并从其load方法中加载该属性。

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

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

Now is there any way to implement my first class's(that build as a class library) Load method to load Ui project's properties after loading it's own properties by using like Dependency Injection. 现在,有什么方法可以实现我的第一个类(作为类库构建)的Load方法,以使用诸如依赖注入之类的方法在加载Ui项目的属性后加载Ui项目的属性。

eg. 例如。

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

It depends what you want. 这取决于您想要什么。 Using separate classes as you have now, you'd need to dependency-inject a list of ICustomerEx objects into each Customer, but then you'd end up with a bunch of different objects each of which would have only a subset of the relevant properties. 像现在一样使用单独的类,您需要将ICustomerEx对象列表依赖注入每个Customer中,但是最终会得到一堆不同的对象,每个对象只有一部分相关属性。 It sounds like inheritance + the template method pattern might be a better fit: 听起来像继承+模板方法模式可能更合适:

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

To support instantiating the customer on the library side, you'll need some way to make the library aware of the UiCustomer class. 为了支持在库侧实例化客户,您需要某种方式使库知道UiCustomer类。

One way to do this would be to register an ICustomerEx with an IOC container and then resolve the instance using dependency injection: 一种方法是在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;
    }
}

Alternatively, you could use a factory pattern: 另外,您可以使用工厂模式:

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

You can call the other implementations like this 您可以像这样调用其他实现

In the assembly that contains the interface ICustomerEx you can add a registry-class that stores instances of ICustomerEx like this 在包含接口ICustomerEx的程序ICustomerEx您可以添加一个注册表类来存储ICustomerEx实例,如下所示

(Note this is pseudocode to show how it could go.) (请注意,这是伪代码以说明如何进行。)

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

every implementation of ICustomerEx needs a call to the registry ICustomerEx的每个实现都需要调用注册表

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

in your main customer class you use the registry to call the other loads 在主要客户类别中,您使用注册表来调用其他负载

public class Customer:ICustomerEx
{
 void Load(DataRow row)
 {
   CustomerRegistry.theRegistry.Load(row);
 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM