C# 业务操作建模:将名称链接到代码
因此,我正在考虑将我的业务操作(或者更确切地说,它们的名称)放到数据库中,这样我就可以将它们链接到用户角色(用于授权)并在操作上设置通知系统 主要的问题是如何将操作(可能由字符串表示,如“Customer.New”或“Customer.View”)从数据库转换为在系统中运行的代码。我想出的大多数方法看起来都很笨拙 示例1-处理所有操作的通用方法C# 业务操作建模:将名称链接到代码,c#,.net,architecture,C#,.net,Architecture,因此,我正在考虑将我的业务操作(或者更确切地说,它们的名称)放到数据库中,这样我就可以将它们链接到用户角色(用于授权)并在操作上设置通知系统 主要的问题是如何将操作(可能由字符串表示,如“Customer.New”或“Customer.View”)从数据库转换为在系统中运行的代码。我想出的大多数方法看起来都很笨拙 示例1-处理所有操作的通用方法 public static object RunOperation(string Op, string User, params object[] Pa
public static object RunOperation(string Op, string User, params object[] Parms)
{
switch(Op)
{
case "Customer.View":
return BLL.Facade.GetCustomerById((int)Parms[0]);
break;
case "Customer.New":
return BLL.Facade.CreateCustomer(Parms[0] as Customer);
break;
...
}
}
我讨厌的是所有的演员。但授权是相当容易的<代码>授权(Op,用户)代码>
然后是这样的:
[BusinessOp("Customer.New")]
public static int CreateCustomer(Customer NewCustomer)
{
...
}
但是授权有点不可靠,因为我假设必须将CreateCustomer方法引用传递到Authorize方法中(不同的操作将具有不同的方法签名)。然后Authorize方法必须使用反射来查找BusinessOpAttribute并获取操作的字符串名称(它在数据库中的表示方式)
我想我可以做的另一件事是创建一系列表示操作字符串名称的常量,并将它们用于Authorize方法,但在执行操作时只调用业务方法。但是,我仍然没有一个项目(无论是方法还是字符串)向所有各方表示业务操作
有没有人有这方面的经验,有没有其他我没有考虑过的选择
回答
最终决定通过评论与接受的答案。我将为每一个业务操作制作一个课程。大概是这样的:
[BusinessOperation]
public static class CustomerNew
{
public const string Key = "Customer.New";
public static bool Authorize(string UserName) // or perhaps IPrincipal User
{
// Authorize method will use key to check against database
...
}
public static int Invoke(Customer NewCustomer)
{
// Invoke method has well-defined parameters
...
// Can also use key to notify listeners of operation completion
}
}
我们处理类似问题的方法是让实际操作表示指定类上的具体方法。最大的问题是参数,我们总是将其留给实现方法来处理 因此,在您的情况下,我将进行如下重构:
var asValues = Op.Split('.');
switch(asValues[0].ToLower())
{
case "customer":
Type type = typeof(BLL.CustomerFacade);
System.Reflection.MethodInfo method = type.GetMethod(asValues[1], System.Reflection.BindingFlags.IgnoreCase);
if (method != null)
{
return method.Invoke(BLL.CustomerFacade, Parms);
}
break;
注意,我将外观更改为CustomerFacade,在这个CustomerFacade中,GetCustomerById将更改为View。这只是一种方法
例如,您还可以将所有内容保存在一个facade中,并将方法名称更改为CustomerView。此外,如果还有其他代码依赖于现有的facade名称,则可以更改操作名称或添加重定向方法,将请求重定向到正确的底层facade方法
这可能需要根据您的实现进行一些调整,但它应该能为您提供总体思路
这种方法的好处是,您不必在每次执行新操作时都更新此方法。谢谢您的回答。这不是我想要的解决方案,因为调用方法仍然必须知道它调用的方法的内部细节(确切地知道要传递哪些参数),这违反了封装原则。但是,如果我找不到更好的解决办法,我可能会做类似的事情。@KaseySpeakman:我同意,这是一种鸡和蛋的情况。但是,您可以通过检查方法的参数,然后询问调用者适当的值来反转控制。例如,您可以添加ValueFetch接口,该接口将由调用者实现,并将根据参数名称或使用反射(假设实现类的值存储在属性中)为参数提供值。然后只传递实现实例,而不是param数组。我正在考虑为每个具有Authorize和Invoke方法的业务操作创建一个类,以及一个const Key,它是操作的数据库名称。Authorize方法将使用密钥来授权操作,但Invoke方法将具有定义良好的参数。这是额外的前期工作,但它确实避免了反射。想法?听起来是个好办法。实际上,我们在移动应用程序视图/模型中使用了非常类似的方法。