我试图寻找解决方案,但我的问题是我甚至不知道使用什么术语。泛型,代表,Linq,反思,抽象的想法可能是解决方案的一部分,但我的“googlephu”没有出现在右边。
问题: 我有多个类(ClassA,ClassB,Class C)都具有相同的2-3个属性DoThisA,DoThisB,DoThisC
代码的工作方式是我总是希望在处理每个类时使用相同的代码来设置DoThisA,DoThisB和DoThisC。
例如,为了简化,逻辑将永远是:
{some computations to set string currentValueImProcessing to something}
if (xyz) [ClassA|B|C].DoThisA = currentValueImProcessing
else [ClassA|B|C].DoThisB = currentValueImProcessing
我不想一遍又一遍地编写那些相同的语句,所以我如何只将类(A,B,C)的引用发送到一个方法来做逻辑
如果写得正确,ClassA,ClassB和ClassC中的每一个都会实现一些泛型类,我可以使用它,但我不能。每个类都是独立的,但具有相同的命名属性。
关于概念/代码的任何指导?
谢谢!
答案 0 :(得分:4)
为您的媒体资源创建interface:
internal interface IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
然后,让你的类实现它:
public class ClassA : IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
public class ClassB : IDoThis
{
// Same properties
}
public class ClassC : IDoThis
{
// Same properties
}
这样,您就可以在某处创建静态初始化方法:
internal static class MyClassesExtensions
{
public static void InitTheStuff(this IDoThis obj)
{
// Do something here, for example:
if (String.IsNullOrEmpty(obj.DoThisA))
obj.DoThisA = "foo";
else
obj.DoThisB = obj.DoThisC;
}
}
然后,您可以在this.InitTheStuff()
,ClassA
和ClassB
的任何地方拨打ClassC
。
答案 1 :(得分:3)
你可以使用反射,也可以使用动态(动态会为你使用反射)
dynamic obj = new ClassA();
obj.DoTHisA();
是如何使用动态
来完成的我假设您正在谈论您打算实例化的类。如果DoThisA,B,C是静态方法,则必须使用反射
注意 - 如果您可以更改类,则按其他人的建议添加接口,或者甚至是公共基类
反射看起来像这样
var type = obj.GetType(); // obj is ClassX object
var method = type.GetMethod("DoTHisA");
method.Invoke(obj);
我没有检查过 - 所以语法可能有点偏离 - 但这是反射方法调用的基本机制。如果有多个具有相同名称的方法,如果方法采用params等,你需要变得更加漂亮
答案 2 :(得分:1)
问你正在谈论继承。
对于您的任务,您需要一个具有常规属性的基本抽象类:
public abstract class Base
{
public bool DoThisA { get; set; }
public bool DoThisB { get; set; }
}
和子课程:
public class A : Base { }
public class B : Base { }
public class C : Base { }
之后,您可以创建一个接受Base
public void Do(Base b, bool xyz, bool currentValueImProcessing)
{
if (xyz)
{
b.DoThisA = currentValueImProcessing;
}
else
{
b.DoThisB = currentValueImProcessing;
}
}
答案 3 :(得分:1)
至少有四种选择 - 或许更多。
作为指导方法1.和2.是首选,因为它们允许在编译时检查代码。但是,如果您无法控制包含常用功能的类 - 例如,您无权访问源代码或者您可以更改代码 - 则可以使用其他两种方法。
如果你问我想要哪两个,我想我会选择3.超过4.但这是个人偏好。
答案 4 :(得分:0)
这里已经提供了很多方法,所以只是为了完整性......这里有一些运行时代码生成:
public class ClassA
{
public string DoThisA { get; set; }
public int DoThisB { get; set; }
public bool DoThisC { get; set; }
public void Init()
{
// You can call this from anywhere, even from an unrelated class
MyClassInitializer<ClassA>.Init(this);
}
}
public static class MyClassInitializer<T>
{
// Create the getters/setters you need, and make sure they're static.
private static readonly Func<T, string> _getA = BuildGetter<string>("DoThisA");
private static readonly Action<T, string> _setA = BuildSetter<string>("DoThisA");
private static readonly Func<T, int> _getB = BuildGetter<int>("DoThisB");
private static readonly Action<T, int> _setB = BuildSetter<int>("DoThisB");
private static readonly Func<T, bool> _getC = BuildGetter<bool>("DoThisC");
private static readonly Action<T, bool> _setC = BuildSetter<bool>("DoThisC");
private static Func<T, TValue> BuildGetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, TValue>>(Expression.Property(obj, name), obj).Compile();
}
private static Action<T, TValue> BuildSetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(TValue));
return Expression.Lambda<Action<T, TValue>>(Expression.Assign(Expression.Property(obj, name), value), obj, value).Compile();
}
public static void Init(T obj)
{
// Here's your custom initialization method
if (_getA(obj) == "Foo")
_setB(obj, 42);
else
_setC(obj, true);
}
}
不一定是最容易掌握的,但这应该比使用dynamic
或反射要快得多。也就是说,如果你不需要速度,请坚持dynamic
,因为它更容易。