我正在开发一个遗留的C#应用程序,它包含许多业务实体类,这些类具有相同名称相同类型的5个公共属性(字符串和整数)。
我需要基于5个常见属性在实体类上实现一些业务流程逻辑。
class A
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class B
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class C
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
// there more of such business classes
public static BusinessHelpr
{
public static DoSomethingOnClassAorBorC(object theRefrence)
{
theRefrence.CommonProperty4 = "result of some complex calculation";
theRefrence.CommonProperty2 = 56; // result of some complex calculation;
theRefrence.CommonProperty5 = "result of some complex calculation";
}
}
如果这是一个绿地应用程序,我会继承一个包含5个属性的基类,并很好地实现所需的逻辑
但是,我们决定不进行任何重构或更改业务实体。他们无法触及。
因此,在我的帮助器类中,我需要找到一种方法来获取对象类型的引用,并通过字符串中的名称访问其属性。 这里一个明显的选择是反思。这意味着我得到一个类型,使用反射来按字符串中的名称访问其属性。 但是,我了解到在这种情况下使用反射意味着性能损失,这不是一个好习惯。
请注意,我简化了实际场景,专注于主要观点。所以创建一个方法不会起作用:
static DoSomethingOnClassAorBorC(string CommonProperty1, int CommonProperty2, string CommonProperty3,string CommonProperty4, string CommonProperty5)
除了反思,我的其他选择是什么?
答案 0 :(得分:3)
我意识到你说你不想对模型做任何改动,但你没有涉及的一个选择是使用界面。
interface ICommon
{
string CommonProperty1 {get;set;}
int CommonProperty2 {get;set;}
string CommonProperty3 {get;set;}
string CommonProperty4 {get;set;}
string CommonProperty5 {get;set;}
}
class A : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class B : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
class C : ICommon
{
public string CommonProperty1 {get;set;}
public int CommonProperty2 {get;set;}
public string CommonProperty3 {get;set;}
public string CommonProperty4 {get;set;}
public string CommonProperty5 {get;set;}
}
然后你可以使用:
static DoSomethingOnClassAorBorC(ICommon common)
{
// implementation
}
你的任何实体都会#34;只是工作"。
您实际上不必对实体进行任何更改,除非向每个实体添加: Interface
,这比使用继承更具侵略性。
如果您确实不想对您的模型进行任何更改,并且不希望产生巨大的性能损失(Reflection和dynamic
都很昂贵),唯一的另一种选择是在每个模型上使用adapter pattern。
interface ICommon
{
string CommonProperty1 {get;set;}
int CommonProperty2 {get;set;}
string CommonProperty3 {get;set;}
string CommonProperty4 {get;set;}
string CommonProperty5 {get;set;}
}
为每个实体创建一个适配器类。
class AAdapter : ICommon
{
private readonly A inner;
public AAdapter(A inner)
{
if (inner == null)
throw new ArgumentNullException(nameof(inner));
this.inner = inner;
}
public string CommonProperty1
{
get { return inner.CommonProperty1; }
set { inner.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return inner.CommonProperty2; }
set { inner.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return inner.CommonProperty3; }
set { inner.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return inner.CommonProperty4; }
set { inner.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return inner.CommonProperty5; }
set { inner.CommonProperty5 = value; }
}
}
class BAdapter : ICommon
{
private readonly B inner;
public BAdapter(B inner)
{
if (inner == null)
throw new ArgumentNullException(nameof(inner));
this.inner = inner;
}
public string CommonProperty1
{
get { return inner.CommonProperty1; }
set { inner.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return inner.CommonProperty2; }
set { inner.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return inner.CommonProperty3; }
set { inner.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return inner.CommonProperty4; }
set { inner.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return inner.CommonProperty5; }
set { inner.CommonProperty5 = value; }
}
}
// Other similar adapters...
以与选项1相同的方式声明方法:
static DoSomethingOnClassAorBorC(ICommon common)
{
// implementation
}
并包装您的实体类以使用它们。
DoSomethingOnClassAorBorC(new AAdapter(a));
DoSomethingOnClassAorBorC(new BAdapter(b));
DoSomethingOnClassAorBorC(new CAdapter(c));
答案 1 :(得分:2)
我能想到的最好的方法是简单地将A,B和C包装在另一个实现接口的类中,比如ICommon:
public interface ICommon
{
string CommonProperty1 { get; set; }
int CommonProperty2 { get; set; }
string CommonProperty3 { get; set; }
string CommonProperty4 { get; set; }
string CommonProperty5 { get; set; }
}
public class A2 : ICommon
{
private readonly A _data;
public A2(A data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
public class B2 : ICommon
{
private readonly B _data;
public B2(B data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
public class C2 : ICommon
{
private readonly C _data;
public C2(C data)
{
_data = data;
}
public string CommonProperty1
{
get { return _data.CommonProperty1; }
set { _data.CommonProperty1 = value; }
}
public int CommonProperty2
{
get { return _data.CommonProperty2; }
set { _data.CommonProperty2 = value; }
}
public string CommonProperty3
{
get { return _data.CommonProperty3; }
set { _data.CommonProperty3 = value; }
}
public string CommonProperty4
{
get { return _data.CommonProperty4; }
set { _data.CommonProperty4 = value; }
}
public string CommonProperty5
{
get { return _data.CommonProperty5; }
set { _data.CommonProperty5 = value; }
}
}
var list = new List<ICommon> { new A2(new A()), new A2(new A()), new B2(new B()), new C2(new C()) };
foreach (var item in list)
{
item.CommonProperty1 = "a";
item.CommonProperty2 = 2;
item.CommonProperty3 = "b";
item.CommonProperty4 = "c";
item.CommonProperty5 = "d";
}