使用设计模式在C#中为类添加function

我的挑战:添加从/向XML序列化和反序列化到只知道如何使用JSON执行此操作的类的function。

我是C#的新手,虽然我熟悉设计模式的“基本”应用程序。

一位同事提出以下建议:

我的建议是你注入一个序列化程序(编写一个IRDCSerizliazer接口,它是一个装饰器/适配器,它包装它所构建的串行器)。

他们在这里的“开放/封闭”原则上非常重要,这可能是为什么建议使用接口和模式而不是在类中添加任何代码。

我刚刚在C#中构建了一个“装饰器”样本模式,以确保我理解如何进行“标准”装饰模式,并且感觉这种情况很复杂……(尽管我很乐意纠正)

我想我需要一些抽象“Serializer”的东西,并允许从我目前只知道JSON的工人类调用Serializer.serialize()和Serializer.deserialize()。我也认为我希望能够拥有JSON代码或“Serializer”中的XML代码基于它的构造方式.IE我从同事的提示中假设他构建了这样的模式……

我可以像他们所说的那样“在我的舌头上”感受到这一点,但是我很难实现这一目标。 “纯粹的”装饰者模式似乎过于复杂。 帮助将不胜感激。

请不要激动我应该如何在办公室寻求更多帮助 – 显然我不想这样做,或者我不会在这里寻求帮助。

我的工作者类在下面 – 你会看到它目前只是直接调用JSON序列化和反序列化……显然这将不得不改变。 不要过分担心它的作用 – 这是一个棘手的reflection内容 – 关键是使用“注入接口”这个概念,可以使用XML和JSON在这个类中进行序列化和反序列化。

namespace XXXXXXXXXXXX { public interface IRecordSearchClientAdapter { string CallCorrectMethod(ClientServiceTypes component, string method, string request, Type[] paramTypes); } public class RecordSearchClientAdapter : IRecordSearchClientAdapter { private IDictionary componentMappings; public static IRecordSearchClientAdapter Create(IDictionary clients) { return new RecordSearchClientAdapter(clients); } private RecordSearchClientAdapter(IDictionary clients) { componentMappings = clients; } public string CallCorrectMethod(ClientServiceTypes component, string method, string request, Type[] paramTypes) { dynamic parsedrequest = Newtonsoft.Json.JsonConvert.DeserializeObject(request); //use another method to decide if it's JSON or XML, don't worry about injecting a Decorator:Interface? //dynamic parsedrequest = DeserializeObject(request); return CallCorrectMethod(component, method, parsedrequest, paramTypes); } //In this method, check for XML or JSON - then forward to the appropriate method. private string DeserializeObject(string request) { //stub - fixme! return null; } private string CallCorrectMethod(ClientServiceTypes component, string method, JObject request, Type[] paramTypes) { object client = componentMappings[component]; MethodInfo mi = FindExactMethod(client, method, request, paramTypes); string response = null; if (paramTypes.Length == 1) // just one "request" object { var obj = DeserializeGenericObject(request, paramTypes[0]); var methodResponse = mi.Invoke(client, new object[] { obj }); response = Newtonsoft.Json.JsonConvert.SerializeObject(methodResponse); } else // multiple parameters, need to grab them from the request { JEnumerable tokens = request.Children(); IEnumerator tokenEnumerator = tokens.GetEnumerator(); List args = new List(); foreach (Type t in paramTypes) { if (!tokenEnumerator.MoveNext()) { throw new ArgumentException("Number of arguments in request doesn't match number of arguments in method"); } args.Add(DeserializeGenericObject(tokenEnumerator.Current.First, t)); } var methodResponse = mi.Invoke(client, args.ToArray()); response = Newtonsoft.Json.JsonConvert.SerializeObject(methodResponse); } return response; } private MethodInfo FindExactMethod(object client, string method, JObject request, Type[] paramTypes) { // get the method that matches the name and type params MethodInfo mi = client.GetType().GetMethod(method, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance, null, paramTypes, null); return mi; } private object DeserializeGenericObject(JToken token, Type objectType) { Type myClassType = this.GetType(); MethodInfo methodToCall = myClassType.GetMethod("DeserializeGenericTemplate", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance); MethodInfo genericMethodToCall = methodToCall.MakeGenericMethod(new Type[] { objectType }); object newObject = genericMethodToCall.Invoke(this, new[] { token }); return newObject; } private T DeserializeGenericTemplate(JToken token) { T obj = token.ToObject(); return obj; } } 

}

不确定为什么你需要在一堂课中。 你的设计似乎有点矫枉过正。 我将有一个接口来定义常见行为(序列化和反序列化)和两个实现类,一个用于JSON,另一个用于XML,类似这样的

 public interface ISerialize { T Deserialize(string input); string Serialize(T type) } public class JsonSerializer : ISerialize { T Deserialize(string input) {...} string Serialize(T type) {...} } public class XmlSerializer : ISerialize { T Deserialize(string input) {...} string Serialize(T type) {...} } 

以下是我将如何使用它

 public class Foo { private ISerializer _serialiser; public Foo(ISerializer serialiser) { _serialiser = serialiser; } void DoFoo() { string result = serialiser.Serialize(instanceOfA_1); var instanceOfA_2 = serialiser.Deserialize(result); } } 

如果您不知道需要哪个序列化程序 – 请使用接口,例如,将其注入构造函数中。

虽然我认为oleksii答案是针对这种情况的最佳设计,但我发布这个作为参考; 在您的问题中,您声明您的学院希望您使用装饰器模式,我不认为装饰器模式在您的情况下是合适的,因为您要添加的新function-XML Parsing-独立于现有类,我的意思是新function不会使用任何现有的类function,因此在oleksii回答中使用的策略模式会更有意义,事实上人们经常会对这两种模式感到困惑,这里有一个答案显示何时以明确的方式使用什么。