如何实现接口并将不同的规则应用于conrete类的实例化
本文关键字:规则 应用于 conrete 实例化 何实现 实现 接口 | 更新日期: 2023-09-27 18:29:04
给定这个类和接口:
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
属性中传递的值应用这些不同的规则来确定匹配?
首先必须创建一个实现接口的类。然后根据类型定义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:
...
}
}
}
(您也可以将此方法添加为Property
上的static
方法)
您可以尝试复合模式:
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;
}
使用此技术,您可以在不更改任何现有代码的情况下添加新的模式匹配器。