如何实现接口并将不同的规则应用于具体类的实例化?

时间:2014-11-04 08:18:45

标签: c# design-patterns

鉴于此类和接口:

public class Property
{
    public string Address { get; set; }
    public string AgencyCode { get; set; }
    public string Name { get; set; }
    public decimal Latitude { get; set; }
    public decimal Longitude { get; set; }
}

public interface IPropertyMatcher
{
    bool IsMatch(Property agencyProperty, Property databaseProperty);
}

假设AgencyCode有三种可能的变体,都有不同的匹配规则:

  • Agency1:匹配.Name.Address
  • Agency2:匹配.Latitude.Longitude
  • Agency3:匹配.Name(反向)

如何以这种方式实现IPropertyMatcher接口,以确定agencyProperty是否与databaseProperty匹配,应用这些不同的规则来确定匹配,具体取决于值{是在agencyProperty.AgencyCode属性中传递的吗?

2 个答案:

答案 0 :(得分:1)

首先,您必须创建一个实现该接口的类。然后根据类型定义IsMatch方法:

public class Agent1Evaluator : IPropertyMatcher
{
    public bool IsMatch(Property agencyProperty, Property databaseProperty)
    {
        return agencyProperty.Name == databaseProperty.Name && agencyProperty.Address == databaseProperty.Address;
    }
}

我相信你可以弄清楚剩下的两个。

或类似的东西:

const string Agent1 = "Agent1";

public class AgentEvaluator : IPropertyMatcher
{
    public bool IsMatch(Property agencyProperty, Property databaseProperty)
    {
        switch (agencyProperty.AgentType)
        {
            case Agent1:
                return agencyProperty.Name == databaseProperty.Name && agencyProperty.Address == databaseProperty.Address;
            case Agent2:
                ...
        }
    }
}

(您可以在static上将此方法添加为Property方法)

答案 1 :(得分:0)

您可以尝试复合模式:

public class CompositePropertyMatcher : IPropertyMatcher
{
    private readonly IEnumerable<IPropertyMatcher> matchers;

    public CompositePropertyMatcher(IEnumerable<IPropertyMatcher> matchers)
    {
        this.matchers = matchers;
    }

    public bool IsMatch(Property agencyProperty, Property databaseProperty)
    {
        return this.matchers.Any(m => m.IsMatch(agencyProperty, databaseProperty));
    }
}

public class PropertyMatcher1 : IPropertyMatcher
{
    public bool IsMatch(Property agencyProperty, Property databaseProperty)
    {
        return agencyProperty.Name == databaseProperty.Name
            && agencyProperty.Address == databaseProperty.Address;
    }
}

public class PropertyMatcher2 : IPropertyMatcher
{
    public bool IsMatch(Property agencyProperty, Property databaseProperty)
    {
        return agencyProperty.Longitude == databaseProperty.Longitude
            && agencyProperty.Latitude == databaseProperty.Latitude;
    }
}

添加DI库不需要注册新的实现。

以下是SimpleInjector

的示例
[Fact]
public void Container_CompositePropertyManager_CallsAllMatchers()
{
    var container = new Container();
    container.RegisterAll<IPropertyMatcher>(this.GetPropertyMatchers());
    container.Register<IPropertyMatcher, CompositePropertyMatcher>();

    var composite = container.GetInstance<IPropertyMatcher>();

    Assert.True(composite.IsMatch(
        new Property { Name = "a", Address = "b", Latitude = 1m, Longitude = 2m },
        new Property { Name = "a", Address = "b", Latitude = 3m, Longitude = 4m }));
    Assert.True(composite.IsMatch(
        new Property { Name = "a", Address = "b", Longitude = 1m, Latitude = 2m },
        new Property { Name = "c", Address = "d", Longitude = 1m, Latitude = 2m }));
    Assert.False(composite.IsMatch(
        new Property { Name = "a", Address = "b", Longitude = 1m, Latitude = 2m },
        new Property { Name = "c", Address = "d", Longitude = 3m, Latitude = 4m }));
}

private IEnumerable<Type> GetPropertyMatchers()
{
    var result =
        from type in typeof(IPropertyMatcher).Assembly.GetTypes()
        where !type.IsAbstract
        where typeof(IPropertyMatcher).IsAssignableFrom(type)
        where type != typeof(CompositePropertyMatcher)
        select type;

    return result;
}

使用此技术,您可以添加新的模式匹配器,而无需更改任何现有代码。