Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在不使用接口的情况下删除冗余C#代码 请考虑两个限制-- 无法将MyProperty移动到接口或抽象类 FooEventHandler是一个dotnet框架方法,因此无法更改参数类型_C#_Wcf - Fatal编程技术网

在不使用接口的情况下删除冗余C#代码 请考虑两个限制-- 无法将MyProperty移动到接口或抽象类 FooEventHandler是一个dotnet框架方法,因此无法更改参数类型

在不使用接口的情况下删除冗余C#代码 请考虑两个限制-- 无法将MyProperty移动到接口或抽象类 FooEventHandler是一个dotnet框架方法,因此无法更改参数类型,c#,wcf,C#,Wcf,我在几个类中定义了MyProperty class A { public string MyProperty { get; set; } } class B { public string MyProperty { get; set; } } class C { public string MyProperty { get; set; } } 方法FooEventHandler为其接

我在几个类中定义了MyProperty

class A
    {
        public string MyProperty { get; set; }
    }
    class B
    {
        public string MyProperty { get; set; }
    }
    class C
    {
        public string MyProperty { get; set; }
    }
方法FooEventHandler为其接收的所有参数更新此属性

public object FooEventHandler(object obj)
    {
        object toReturn = null;
        if (obj.GetType() == typeof(A))
        {
            (obj as A).MyProperty = "updated";
            toReturn = obj;
        }
        else if (obj.GetType() == typeof(B))
        {
            (obj as B).MyProperty = "updated";
            toReturn = obj;
        }
        else if (obj.GetType() == typeof(C))
        {
            (obj as C).MyProperty = "updated";
            toReturn = obj;
        }
        return toReturn;
    }
FooEventHandler会像这样重复调用-

static void Main(string[] args)
    {
        Program program = new Program();
        A objA = new A();
        program.FooEventHandler(objA);
        B objB = new B();
        program.FooEventHandler(objB);
        C objC = new C();
        program.FooEventHandler(objC);
    }
请建议一种删除Foo中冗余代码的方法,一般考虑上述两个限制

更准确地说,我在WCF中使用ParameterInspector时遇到了这个问题。我正在尝试修改这里截获的所有请求的属性,并且必须基于operationName编写开关用例

A、B、C、D上述类别是代理。所以我不想一开始就修改它们。因为更新服务引用将覆盖我的iterface更改

public object BeforeCall(string operationName, object[] inputs){
    // update inputs[0] properties
    }

感谢您的帮助。

假设您可以使用
dynamic

dynamic toReturn = obj;
toReturn.MyProperty = "updated";
return toReturn;
如果
obj
上不存在
MyProperty
,则会引发此错误

测试:

[Test]
public void X()
{
    A objA = new A();
    var x = FooEventHandler(objA);
    Assert.IsInstanceOf<A>(x);
    Assert.AreEqual("updated", (x as A).MyProperty);

    B objB = new B();
    var y = FooEventHandler(objB);
    Assert.IsInstanceOf<B>(y);
    Assert.AreEqual("updated", (y as B).MyProperty);

    C objC = new C();
    var z = FooEventHandler(objC);
    Assert.IsInstanceOf<C>(z);
    Assert.AreEqual("updated", (z as C).MyProperty);

    D objD = new D();
    Assert.Throws<RuntimeBinderException>(() => FooEventHandler(objD));
}

class D {}
[测试]
公共空间X()
{
A objA=新的A();
var x=FooEventHandler(objA);
Assert.IsInstanceOf(x);
Assert.AreEqual(“更新的”,(x作为.MyProperty);
B objB=新的B();
var y=FooEventHandler(objB);
断言。IsInstanceOf(y);
Assert.AreEqual(“更新的”,y为B.MyProperty);
C objC=新的C();
var z=FooEventHandler(objC);
Assert.IsInstanceOf(z);
Assert.AreEqual(“更新的”,(z为C.MyProperty);
D objD=新的D();
抛出(()=>FooEventHandler(objD));
}
类D{}

我的第一个想法是在事件处理程序中使用反射:

public object FooEventHandler(object obj)
{
    obj.GetType().GetProperty("MyProperty").SetValue(obj, "updated", null);
    return obj;
}

使用反射,可以检查这些条件,然后设置值:

  • 具有所需的属性
    MyProperty
  • MyProperty
    的类型为
    string
  • MyProperty
    有一个setter

  • 实际上,您可以让您的类实现一个接口,以使其更易于使用。关键是生成的服务引用类是部分的,这意味着您可以在单独的文件中执行此操作,重新生成代码时不会覆盖该文件:

    namespace ServiceReferenceNamespace {
     public partial class A : IMyProperty { }
     public partial class B : IMyProperty { }
     public partial class C : IMyProperty { }
    }
    
    其中
    IMyProperty
    为:

    public interface IMyProperty { string MyProperty { get; set; } }
    
    然后,您可以将
    FooEventHandler
    方法更改为获取
    IMyProperty
    ,或者获取
    对象
    并检查
    obj是否为IMyProperty
    (或者将
    用作
    ,因此检查只执行一次)。这使您可以简单地使用该属性,而不会产生任何反射或动态复杂性以及这些方法对运行时性能的影响。

    Edit
    蒂姆的答案可能是最简单、最安全的。但是,分部类必须全部位于同一程序集中。如果由于某种原因无法编辑包含代理类的程序集,您仍然可以这样做

    原始答案

    这可能有点过分

    创建一个新的界面

    public interface IProxyWrapper
    {
        string MyProperty { get; set; }
    }
    
    执行
    AWrapper
    /
    bwraper
    cwraper
    。有两种不同的方法可以做到这一点。我将只显示
    A
    ,因为从那里开始剩下的应该很简单

    public class AWrapper : IProxyWrapper
    {
        public string MyProperty { get; set; }
    }
    

    第二种方法的好处是,您可以在任何可以使用
    A
    的地方使用
    AWrapper

    无论哪种方式,您都需要找到一种方法,将值从包装器中获取到代理类中。您可以使用AutoMapper之类的工具来设置属性,或者将其作为构造函数参数传入,存储在字段中,并实现
    IProxyWrapper.MyProperty
    来包装
    a.MyProperty

    至于将值返回到代理,还有AutoMapper,或者您可以以某种方式公开该字段


    现在,您可以为您的应用程序进一步自定义这些包装器类,而不用担心在重新生成代理时丢失它。

    是的,
    dynamic
    是一个非常好的解决方案。当a B不是部分类时,从a继承AWrapper的想法非常棒。
    public class AWrapper : IProxyWrapper
    {
        public string MyProperty { get; set; }
    }
    
    public class AWrapper : A, IProxyWrapper
    {
        string IProxyWrapper.MyProperty 
        { 
            get { return base.MyProperty; }
            set { base.MyProperty = value; }
        }
    }