C# 如何提供默认公共构造函数并禁止使用外部反射

C# 如何提供默认公共构造函数并禁止使用外部反射,c#,constructor,postsharp,C#,Constructor,Postsharp,我正在寻找一种方法来创建一个具有默认公共构造函数的类,但它禁止在反射之外使用 更详细地说,我正在使用一个对象持久性框架(AWS DynamoDB-我没有更改的选项),它要求对象实现这样一个公共默认构造函数。该框架还要求所有持久化字段和属性也具有公共get和set访问器,并在创建和初始化新对象实例时使用它们。这会导致问题,因为访问器需要满足双重目的——当框架使用它们时,它们需要是“裸”的,但当代码使用它们时,它们需要强制执行限制和验证。无论如何,我已经解决了这一部分,但它依赖于永远不允许代码使用默

我正在寻找一种方法来创建一个具有默认公共构造函数的类,但它禁止在反射之外使用

更详细地说,我正在使用一个对象持久性框架(AWS DynamoDB-我没有更改的选项),它要求对象实现这样一个公共默认构造函数。该框架还要求所有持久化字段和属性也具有公共get和set访问器,并在创建和初始化新对象实例时使用它们。这会导致问题,因为访问器需要满足双重目的——当框架使用它们时,它们需要是“裸”的,但当代码使用它们时,它们需要强制执行限制和验证。无论如何,我已经解决了这一部分,但它依赖于永远不允许代码使用默认构造函数(持久性框架使用的构造函数)构造持久化对象

回到最初的问题——为了让这一切都能正常工作,我需要禁止代码使用默认构造函数,同时仍然让持久性框架(只搜索空的公共构造函数)可以使用它。我首先使用一个静态标志,在任何潜在的对象持久性使用之前和之后设置它,如果没有设置,则在默认构造函数中抛出一个异常,但这在多线程环境(web服务器)中开始导致问题。一个线程会将其设置为供持久性框架使用,持久性框架会打开构造函数供其他线程使用。我还尝试了ThreadStatic标志,但它有相反的问题,即阻止框架进行构造,因为它有时会生成工作线程


现在我想知道是否真的有办法做到这一点。在这一点上,它变得更像是一种好奇心,而不是一种需求;我总是可以写一条注释,大意是“不要使用这个构造函数”,但是直接执行规则会让我感觉更好。我以前使用过PostSharp,也许有一种方法可以使用方面进行编译时验证,以防止使用基于代码的默认构造函数?还有其他建议吗?

我不会在这上面花太多时间。不会有一个“干净”的方法去做,你会浪费大量的周期去尝试。让调用方负责使用,只需明智地注释代码即可

WinForms中也存在同样的问题,要求表单中的无参数构造函数支持VS设计器,而调用方在正常使用表单时必须提供某些参数(例如,要显示的输入数据集)

如果您真的想这样做,一种方法可以是在默认构造函数中使用反射来确定调用方,如果调用方程序集不是DynamoDB,则抛出异常

if (!Assembly.GetCallingAssembly().FullName.Contains("DynamoDB"))
    throw new InvalidOperationException("BEGONE!");
另外,作为补充说明,我通常将这些“开发人员”检查作为Debug.Asserts而不是异常来实现。通过这种方式,您在开发过程中引入了您所追求的保护,但在生产过程中(假设发布构建),不会编译断言,并且不会在每次调用时产生(轻微的)性能影响

Debug.Assert(Assembly.GetCallingAssembly().FullName.Contains("DynamoDB"), "Invalid constructor usage");

使用PostSharp,您可以使用来验证某些构造函数是否未从用户代码中调用(执行引用约束并将约束附加到类,可能使用多播和继承)。基本上,如果此代码的唯一合法使用来自反射,则如果您找到对构造函数的任何引用(除了来自其他构造函数的链接),则可能会发出错误

请注意,这不会阻止从
new T()
构造调用构造函数,其中T是泛型类型参数。因此,仅禁止使用新运算符:从ReferentialSpect中,使用ReflectionSearch.GetMethodsSusingDeclaration和filter for
(Instructions&MethodUsageInstructions.NewObject)!=0


编辑:添加了关于ReflectionSearch.GetMethodsUsingDeclaration和MethodUsageInstructions的详细信息。

是的,这就是我要实现的——幸运的是并没有花太多时间。我没有想过检查调用程序集-聪明。这是完美的。我认为PostSharp可以处理它,因为它已经在验证方面做了基本相同的事情。谢谢,哎呀。您希望允许另一个构造函数调用链中禁止的构造函数。编辑了我的答案。