Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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# 使包装类的扩展方法/构造函数成为泛型_C#_Wpf_Generics_Wrapper - Fatal编程技术网

C# 使包装类的扩展方法/构造函数成为泛型

C# 使包装类的扩展方法/构造函数成为泛型,c#,wpf,generics,wrapper,C#,Wpf,Generics,Wrapper,在一个服务(我无法更改)中,我有两个对象类Bar和Baz,它们的属性基本相似(但遗憾的是,它们不是从同一个基类派生的,也不是从同一个接口继承的……是的——愚蠢),以及与其相对BarQux和BazQux属性相关的依赖类: public class Bar public class Baz { { public int ID { get; set; }

在一个服务(我无法更改)中,我有两个对象类
Bar
Baz
,它们的属性基本相似(但遗憾的是,它们不是从同一个基类派生的,也不是从同一个接口继承的……是的——愚蠢),以及与其相对
BarQux
BazQux
属性相关的依赖类:

public class Bar                          public class Baz
{                                         {
    public int ID { get; set; }               public int ID { get; set; }
    public bool Active { get; set; }          public bool Active { get; set; }
    public int BarQux { get; set; }           public int BazQux { get; set; }
    ...                                       ...
}                                         }

public class Qux
{
    public int ID { get; set; } // Corresponds to BarQux and BazQux
    public string Name { get; set; }
}
在WPF屏幕中,我将每种类型的列表(
Baz
Bar
)绑定到两个独立的列表视图。我需要每个都有一个额外的
选中的
复选框列。为此,我创建了一个包装类,其中包含公共属性、附加的
Selected
属性以及每个属性的构造函数:

public class Foo
{
    public Foo(Bar bar, Qux qux)
    {
        this.Active = bar.Active;
        this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        ...
    }

    public Foo(Baz baz, Qux qux)
    {
        this.Active = baz.Active;
        this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        ...
    }

    public bool Selected { get; set; }
    public int ID { get; set; }
    public bool Active { get; set; }
    public string FooQux { get; set; }
    ...
}
为了将类
Baz
Bar
的每个集合转换为
Foo
的集合,我创建了以下扩展方法:

public static List<Foo> ToFoo(this IEnumerable<Bar> bars, IEnumerable<Qux> quxs)
{
    List<Foo> foos = new List<Foo>();

    foreach (Bar bar in bars)
    {
        Foo foo = new Foo(bar, quxs.Single(qux => qux.ID == bar.BarQux));
        foos.Add(foo);
    }

    return foos;
}

public static List<Foo> ToFoo(this IEnumerable<Baz> bazs, IEnumerable<Qux> quxs)
{
    List<Foo> foos = new List<Foo>();

    foreach (Baz baz in bazs)
    {
        Foo foo = new Foo(baz, quxs.Single(qux => qux.ID == baz.BazQux));
        foos.Add(foo);
    }

    return foos;
}
  • 更改构造函数以接收整个
    Qux
    对象集合,并在其中执行
    quxs.Single(Qux=>Qux.ID==object.ObjectQux)
    逻辑。然后将扩展方法变成一个泛型方法,如下所示

    public static List<Foo> ToFoo<T>(this IEnumerable<T> objCollection, IEnumerable<Qux> quxs)
    {
        List<Foo> foos = new List<Foo>();
    
        foreach (T obj in objCollection)
        {
            Foo foo = new Foo(obj, quxs); // The best overloaded method... has some invalid arguments.
            foos.Add(foo);
        }
    
        return foos;
    }
    
    公共静态列表ToFoo(此IEnumerable对象集合,IEnumerable QUX)
    {
    List foos=新列表();
    foreach(对象集合中的T对象)
    {
    Foo Foo=new Foo(obj,quxs);//最好的重载方法…有一些无效参数。
    添加(foo);
    }
    返回foos;
    }
    
  • 1和2的组合?有什么我没想到的吗


  • 如果属性有限,并且列表中的项目数也很少,则可以使用
    反射
    。由于您将在WPF中使用它,我还建议将该进程移动到单独的后台线程

    通用Foo

    public class Foo<T>
    {
        public Foo(T obj, Qux qux)
        {
            //this.Active = obj.Active;
    
            var fooProps = GetType().GetProperties().ToList();
            var tProps = typeof(T).GetProperties()
                .Where(p =>
                {
                    var w = fooProps.FirstOrDefault(f => f.Name == p.Name);
                    return w != null;
                }).ToList();
    
            foreach (var propertyInfo in tProps)
            {
                var val = propertyInfo.GetValue(obj);
                fooProps.First(e => e.Name == propertyInfo.Name).SetValue(this, val);
            }
            this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        }
        public bool Selected { get; set; }
        public int ID { get; set; }
        public bool Active { get; set; }
        public string FooQux { get; set; }
    }
    
    然后您可以调用
    ToFoo
    扩展方法,瞧,您有一个Foo列表


    您还可以使用
    Qux
    class

    的逻辑将Foo转换为非泛型,我看不出这样做有什么好处

    如果您坚持使用泛型,您可以在T上执行一些类型检查,如下所示:

    public class Foo<T>
    {
        public Foo(T obj, Qux qux)
        {
            var baz = obj as Baz;
            var bar = obj as Bar;
    
            Active = baz != null && baz.Active || bar != null && bar.Active;
    
            this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        }
    
        public bool Selected { get; set; }
        public int ID { get; set; }
        public bool Active { get; set; }
        public string FooQux { get; set; }
    }
    
    公共类Foo
    {
    公共食品(T obj,Qux Qux)
    {
    var baz=作为baz的obj;
    var bar=obj as bar;
    Active=baz!=null&&baz.Active | | bar!=null&&bar.Active;
    this.FooQux=string.Format(“{0}-{1}”,qux.ID,qux.Name);
    }
    已选择公共布尔值{get;set;}
    公共int ID{get;set;}
    公共bool活动{get;set;}
    公共字符串FooQux{get;set;}
    }
    
    或:

    公共静态列表ToFoo(此IEnumerable对象集合,IEnumerable QUX)
    {
    List foos=新列表();
    foreach(对象集合中的T对象)
    {
    var baz=作为baz的obj;
    var bar=obj as bar;
    Foo-Foo=null;
    如果(baz!=null)
    foo=newfoo(baz,quxs.Single(qux=>qux.ID==baz.BazQux));
    如果(bar!=null)
    foo=newfoo(bar,quxs.Single(qux=>qux.ID==bar.BarQux));
    如果(foo!=null)
    添加(foo);
    }
    返回foos;
    }
    
    但这显然并不比您已有的好多少,如果t不是Bar或Baz(未显示),您将不得不执行一些异常处理,这将使您面临潜在的运行时故障。您也可以使用反射,但也可以使用反射


    不幸的是,使用C#不可能实现您正在寻找的功能。如果接口是鸭型a-la Golang,则唯一可以避免这种情况的方法是,但事实并非如此。

    根据Sandesh的建议,最终结果:

    public class Foo<T>
    {
        public Foo() {}
    
        public Foo(T obj, IEnumerable<Qux> quxs, string quxPropName)
        {
            var fooProps = GetType().GetProperties().ToList();
            var tProps = typeof(T).GetProperties()
                .Where(p =>
                {
                    var w = fooProps.FirstOrDefault(f => f.Name == p.Name);
                    return w != null;
                }).ToList();
    
            foreach (var propertyInfo in tProps)
            {
                var val = propertyInfo.GetValue(obj, null);
                fooProps.First(e => e.Name == propertyInfo.Name).SetValue(this, val, null);
            }
    
            int id = (int)typeof(T).GetProperty(quxPropName).GetValue(obj, null);
            Qux qux = quxs.Single(q => q.ID == id);
            this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        }
    
        public bool Selected { get; set; }
        public int ID { get; set; }
        public bool Active { get; set; }
        public string FooQux { get; set; }
    }
    
    公共类Foo
    {
    公共Foo(){}
    public Foo(T obj,IEnumerable qux,string quxPropName)
    {
    var fooProps=GetType().GetProperties().ToList();
    var tProps=typeof(T).GetProperties()
    .其中(p=>
    {
    var w=fooProps.FirstOrDefault(f=>f.Name==p.Name);
    返回w!=null;
    }).ToList();
    foreach(tProps中的var propertyInfo)
    {
    var val=propertyInfo.GetValue(obj,null);
    fooProps.First(e=>e.Name==propertyInfo.Name).SetValue(this,val,null);
    }
    int id=(int)typeof(T).GetProperty(quxPropName).GetValue(obj,null);
    Qux=Qux.Single(q=>q.ID==ID);
    this.FooQux=string.Format(“{0}-{1}”,qux.ID,qux.Name);
    }
    已选择公共布尔值{get;set;}
    公共int ID{get;set;}
    公共bool活动{get;set;}
    公共字符串FooQux{get;set;}
    }
    
    和通用扩展方法:

    public static List<Foo<T>> ToFoo<T>(this IEnumerable<T> list, IEnumerable<Qux> quxs, string quxPropName)
    {
        List<Foo<T>> foos = null;
    
        try
        {
            foos = list.Select(obj => new Foo<T>(obj, quxs, quxPropName)).ToList();
        }
        catch
        {
            foos = new List<Foo<T>>();
        }
    
        return foos;
    }
    
    公共静态列表ToFoo(此IEnumerable列表、IEnumerable qux、字符串quxPropName)
    {
    列表foos=null;
    尝试
    {
    foos=list.Select(obj=>newfoo(obj,quxs,quxPropName)).ToList();
    }
    抓住
    {
    foos=新列表();
    }
    返回foos;
    }
    
    使用方法:

    List<Foo<Bar>> bars = barCollection.ToFoo(quxCollection, "BarQux");
    List<Foo<Baz>> bazs = bazCollection.ToFoo(quxCollection, "BazQux");
    
    List bar=barCollection.ToFoo(quxCollection,“BarQux”);
    List baz=bazCollection.ToFoo(quxCollection,“BazQux”);
    
    你可能想检查一下,你不能修改文件还是不能修改类?例如,您可以实现一个分部类。但是您必须将原始类更改为分部类。@ScottNimrod我无法修改服务中的任何类或文件,例如
    Baz
    类型
    类。如果可以的话,我想让前两个继承自基类或接口-这将使我在泛化方面的有限经验更容易实现。这看起来像是一个DTO对象到/从BusinessObject的案例。您可以完全控制businessObject实现,但DTO对象实际上来自“难以”更改的外部服务。我有一个场景,在这个场景中,当我被告知可能会有一些mor时,应用程序开发已经进行了一半
    public static List<Foo> ToFoo<T>(this IEnumerable<T> objCollection, IEnumerable<Qux> quxs)
    {
        List<Foo> foos = new List<Foo>();
    
        foreach (T obj in objCollection)
        {
            var baz = obj as Baz;
            var bar = obj as Bar;
    
            Foo foo = null;
    
            if(baz != null)
                foo = new Foo(baz, quxs.Single(qux => qux.ID == baz.BazQux));
    
            if(bar != null)
                foo = new Foo(bar, quxs.Single(qux => qux.ID == bar.BarQux));
    
            if(foo != null)
                foos.Add(foo);
        }
    
        return foos;
    }
    
    public class Foo<T>
    {
        public Foo() {}
    
        public Foo(T obj, IEnumerable<Qux> quxs, string quxPropName)
        {
            var fooProps = GetType().GetProperties().ToList();
            var tProps = typeof(T).GetProperties()
                .Where(p =>
                {
                    var w = fooProps.FirstOrDefault(f => f.Name == p.Name);
                    return w != null;
                }).ToList();
    
            foreach (var propertyInfo in tProps)
            {
                var val = propertyInfo.GetValue(obj, null);
                fooProps.First(e => e.Name == propertyInfo.Name).SetValue(this, val, null);
            }
    
            int id = (int)typeof(T).GetProperty(quxPropName).GetValue(obj, null);
            Qux qux = quxs.Single(q => q.ID == id);
            this.FooQux = string.Format("{0} - {1}", qux.ID, qux.Name);
        }
    
        public bool Selected { get; set; }
        public int ID { get; set; }
        public bool Active { get; set; }
        public string FooQux { get; set; }
    }
    
    public static List<Foo<T>> ToFoo<T>(this IEnumerable<T> list, IEnumerable<Qux> quxs, string quxPropName)
    {
        List<Foo<T>> foos = null;
    
        try
        {
            foos = list.Select(obj => new Foo<T>(obj, quxs, quxPropName)).ToList();
        }
        catch
        {
            foos = new List<Foo<T>>();
        }
    
        return foos;
    }
    
    List<Foo<Bar>> bars = barCollection.ToFoo(quxCollection, "BarQux");
    List<Foo<Baz>> bazs = bazCollection.ToFoo(quxCollection, "BazQux");