gpt4 book ai didi

.net - 关于 "remoting"的最佳实践,一个带有 WCF 的 .NET 类库

转载 作者:行者123 更新时间:2023-12-05 01:31:01 24 4
gpt4 key购买 nike

我有一个大型 .NET 4.5 类库,其中包含 60 多个类和许多公共(public)方法。这用作我的应用程序的编程接口(interface)。现在我想使用 WCF 通过网络调用这个库。执行此操作的最佳做​​法是什么?

一种天真的方法是用 WCF 服务库包装我的类库,该服务库复制原始类库的类和方法结构,其中每个方法都有一个方法。然而,这似乎有点矫枉过正,并且违背了使网络接口(interface)变得粗壮而不是繁琐的原则。那么应该如何构建WCF服务库呢?它应该有什么样的结构?是否有任何公认的最佳实践指南?谢谢。

最佳答案

不知道这是否是“最佳”做法,但我已经看到这样做了:

使数据协定成为一个方法,该方法将操作和参数数组作为参数。然后在服务端通过反射获取实现方法,简单的传递参数数组即可。这是我整理的一个快速示例(并经过测试,它有效)。

契约(Contract):

namespace GenericWcfService
{
[ServiceKnownType(typeof(Pair))] //there's another way to add more, look it up
[ServiceContract]
public interface ICalculatorService
{
[OperationContract]
OperationResult GetResult(Operation op, object[] parameteres);
}

public enum Operation
{
Add,
Substract,
Multiply,
Divide,
Print,
AddPair
}

[DataContract]
public class OperationResult
{
[DataMember]
public object Result { get; set; }

[DataMember]
public string Error { get; set; }
}

[DataContract]
public class Pair
{
[DataMember]
public int V1;
[DataMember]
public int V2;
}
}

服务器:

namespace GenericWcfService
{
public class CalculatorService : ICalculatorService
{
public OperationResult GetResult(Operation op, object[] parameteres)
{
var calc = new CalculatorImpl();
var method = typeof(CalculatorImpl).GetMethod(op.ToString());

var result = new OperationResult();
if (method == null) { result.Error = "Incompatible"; return result; }
var mParameters = method.GetParameters();
if (mParameters.Length != parameteres.Length) { result.Error = "Incompatible"; return result; }
for (int i = 0; i < parameteres.Length; i++)
{
try
{
var paramVal = Convert.ChangeType(parameteres[i], mParameters[i].ParameterType);
}
catch (Exception)
{
{ result.Error = $"Parameter [{i}]({mParameters[i]})={parameteres[i]} is incompatible"; return result; }
}
}


try
{
result.Result = method?.Invoke(calc, parameteres);
}
catch (Exception e)
{
result.Error = e.Message;
}
return result;
}
}

public class CalculatorImpl
{
public int Add(int p1, int p2)
{
return p1 + p2;
}

public string Print(string text, int n1)
{
return $"{text}: {n1}";
}

public int AddPair(Pair p)
{
return p.V1 + p.V2;
}
}
}

客户:

class Program
{
static void Main(string[] args)
{
var calc = new CalculatorServiceClient();
var result = calc.GetResult(Operation.Add, new object[] { 2, 3 });
if (string.IsNullOrEmpty(result.Error))
Console.WriteLine(result.Result);
else
Console.WriteLine(result.Error);

result = calc.GetResult(Operation.Print, new object[] { "result", result.Result });
if (string.IsNullOrEmpty(result.Error))
Console.WriteLine(result.Result);
else
Console.WriteLine(result.Error);

result = calc.GetResult(Operation.Add, new object[] { 2, "c3" });
if (string.IsNullOrEmpty(result.Error))
Console.WriteLine(result.Result);
else
Console.WriteLine(result.Error);

result = calc.GetResult(Operation.AddPair, new object[] { new Pair { V1 = 3, V2 = 4 } });
if (string.IsNullOrEmpty(result.Error))
Console.WriteLine(result.Result);
else
Console.WriteLine(result.Error);

Console.ReadKey();
}
}

输出:

5
result: 5
Parameter [1](Int32 p2)=c3 is incompatible
7
  1. 我本来打算提到参数验证,但后来我继续做了,使用反射来验证计数和 object 参数可以转换。
  2. 然后我想到了复杂的对象......是的,它们可以作为参数数组中的 object 发送(并且它们通过上面的方法正确验证),但它们需要通过服务。要在服务定义中包含未使用的类,请使用 ServiceKnownType 属性。
  3. 拥有这种服务定义开启了一个全新的机会水平(对于困惑!:))您可以将值添加到 Operation 枚举的 end 上服务器,而不是破坏客户端。或者使用 string 作为操作代码(不要使用复杂类型作为参数,请参见 2.)然后开始吧!!!多个版本的服务器与多个版本的客户端协商,部分服务器实现......成为可能,显然需要一些版本控制和发现逻辑(在中央服务上?)

总而言之:我对上面的第 3 点有点不知所措,我在那里描述的内容肯定与 WCF 服务的最佳实践完全相反。如果我没记错的话,更改服务器会破坏客户端这一事实被认为是 WCF 的优势之一。但我仍然认为上述解决方案对某些场景有效,例如

  • 在服务中快速包装一个大型库,该库不会改变,或者客户不介意不总是从中得到响应

  • 当客户端数量众多且无法快速更新时允许某种程度的灵 active ,因此不同版本需要并行工作。

关于.net - 关于 "remoting"的最佳实践,一个带有 WCF 的 .NET 类库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48235538/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com