我有两个名为Run
的方法看起来几乎相同,但它们使用不同的类型:
public string Run<T>(IEnumerable<T> items)
{
// ... Code
var serializer = new ObjectSerializer<T>();
var headers = serializer.SerializeHeaders(items);
// ... Code
foreach (var item in items)
{
var values = serializer.SerializeValues(item);
// ... Code
}
// ... Code
}
public string Run<T>(IEnumerable<Wrapper<T>> items)
{
// ... Code
var serializer = new ObjectWrapperSerializer<T>();
var headers = serializer.SerializeHeaders(items);
// ... Code
foreach (var item in items)
{
var values = serializer.SerializeValues(item);
// ... Code
}
// ... Code
}
public class ObjectSerializer<T>
{
public string[] SerializeHeaders(IEnumerable<T> items) { ... }
public string SerializeValues(T item) { ... }
}
public class ObjectWrapperSerializer<T>
{
public string[] SerializeHeaders(IEnumerable<Wrapper<T>> items) { ... }
public string SerializeValues(Wrapper<T> item) { ... }
}
两种方法中的所有// ... Code
部分都相同。 Wrapper<T>
有一个T的实例,但除此之外,它们没有任何共同之处。
我想删除重复,但我不知道该怎么做。
有什么建议吗?
答案 0 :(得分:3)
如果唯一不同的是所需的序列化程序,您可以将其作为参数传递吗?像这样:
public class Runner
{
private string Run<T>(IEnumerable<T> items, IObjectSerializer<T> serializer)
{
// ... Code
var headers = serializer.SerializeHeaders(items);
// ... Code
foreach (var item in items)
{
var values = serializer.SerializeValues(item);
// ... Code
}
// ... Code
}
public string Run<T>(IEnumerable<T> items)
{
return Run(items, new ObjectSerializer<T>());
}
public string Run<T>(IEnumerable<Wrapper<T>> items)
{
return Run(items, new ObjectWrapperSerializer<T>());
}
}
public interface IObjectSerializer<T>
{
string[] SerializeHeaders(IEnumerable<T> items);
string SerializeValues(T item);
}
public class ObjectSerializer<T>: IObjectSerializer<T>
{
public string[] SerializeHeaders(IEnumerable<T> items) { ... }
public string SerializeValues(T item) { ... }
}
public class ObjectWrapperSerializer<T> : IObjectSerializer<Wrapper<T>>
{
public string[] SerializeHeaders(IEnumerable<Wrapper<T>> items) { ... }
public string SerializeValues(Wrapper<T> item) { ... }
}
(还没有Visual Studio,所以可能不是100%正确!)
答案 1 :(得分:0)
如果你看一下你的逻辑,第二种方法是第一种方法的一个特例:如果T就像Wrapper那样,做其他事情(ObjectWrapperSerializer);否则做正常的事情(ObjectSerializer)。
所以这个想法是,你想通过查看T来动态决定在运行时做什么。你怎么做?反射!
if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Wrapper<>)){
Type u = typeof(T).GetGenericArguments()[0]; //u is the type in Wrapper<U>
MethodInfo method = TheGenericWrapperMethod;
MethodInfo gMethod = method.MakeGenericMethod(new Type[] { u });
gMethod.Invoke();
} else {
//do the normal thing
}
或者,您可以查看工厂模式:创建一个工厂类,它在运行时生成ObjectSerializer或ObjectWrapperSeralizer实例(当然,您必须具有某种类型的契约,如继承或接口或抽象类等)。
代码不是100%准确,但我希望它会指向正确的方向。