我正在写一个在.net和silverlight之间共享的库。我有几个地方在做这个,以满足silverlight反序列化(无法访问私人成员):
[DataMember (IsRequired = true)]
public Object MyProperty { get;
#if SILVERLIGHT
internal
#else
private
#endif
set; }
我知道这个规则,如果setter是私有的并且定义了SILVERLIGHT,那么setter应该是内部的。
我可以使用像postsharp这样的面向方面的框架来帮助我减少这些代码,这样我就不需要指定任何内容了,它会检查属性,如果它具有DataMember属性并且setter是私有的,那么请设置内部而不是?
或者我可以使用其他技术吗?
编辑
似乎有些混乱。我的目标是完全避免使用编译器指令,但仍然拥有使用.net中的私有成员生成的代码以及可由DataContractDeserializer
设置的成员Silverlight,无法访问私有成员。如果可能的话,我想自动修改silverlight构建中的属性,使其成为内部属性,同时除了源代码中的DataMember
属性之外没有其他内容。
理想情况下,我认为解决方案类似于:
[DataMember]
属性,那么
但是我不确定使用post sharp这样的工具可以做到哪些。
答案 0 :(得分:3)
其他答案要么攻击问题的优点,要么提出不直接回答问题的替代方法。问题是,在编译后,是否有办法在具有DataMember属性的属性中更改setter的可见性,以支持两个版本(.NET和Silverlight)。
我怀疑PostSharp SDK会支持这一点。但是,这是我在开发Afterthought时必须解决的问题,因为我需要更改由C#编译器生成的匿名静态委托的可见性(通常是私有的,直到我将它们设置为内部)。事后补充本身目前不直接支持您的场景,但它利用了开源Microsoft CCI库。 IL Mutator示例演示了如何使用CCI库加载已编译的程序集并通过创建可变副本来修改它。这个例子实际上比你的场景复杂得多,因为你不会修改IL,只是设置器的可见性。
这是在CCI中从mutator中更改方法可见性的示例:
public override MethodDefinition Mutate(MethodDefinition methodDef)
{
// Automatically make all private static methods to have internal scope
if (methodDef.IsStatic && methodDef.Visibility == TypeMemberVisibility.Private)
methodDef.Visibility = TypeMemberVisibility.Assembly;
这是一个稍微简化的excerpt来自事后的支持者。在同一个类中还有一些示例,用于确定方法是否为setter(以set_,HideBySig等开头)。您只需要创建一个mutator,覆盖此示例中的方法,验证该方法是包含属性定义的DataMember属性的属性设置器,并更改可见性。
答案 1 :(得分:1)
简单的答案是否定的。 PostSharp是一个后编译框架,所以你不能使用你的编译器指令(正如你在你的问题中尝试做的那样)。您可以使用PostSharp
另一种方法是使用T4模板为您生成这些类
编辑:属性注入示例
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
public class PropInj : InstanceLevelAspect
{
#if SILVERLIGHT
[IntroduceMember(OverrideAction = MemberOverrideAction.Ignore, IsVirtual=true, Visibility=Visibility.FamilyAndAssembly)]
public string MyProperty { get; set; }
#else
[IntroduceMember(OverrideAction = MemberOverrideAction.Ignore, IsVirtual = true, Visibility = Visibility.Private)]
public string MyProperty { get; set; }
#endif
}
[PropInj]
public class test
{
//public int MyProperty { get; set; }
public test()
{
}
}
但实际上你需要重新考虑你的设计。