【问题标题】:Is there a jQuery extend in c#?c# 中是否有 jQuery 扩展?
【发布时间】:2014-11-27 04:35:51
【问题描述】:
 var _Contact = new ContactLstModel { 
             ContactName="xxxxxx",
              EmailAddr="yyyyyy",
               ContactNo="ddddddd",
               SelectedContactType="dddd"
            };

 var _ContactOption= new ContactLstModel{
                 ContactType= new List<SelectListItem>(){
                 new SelectListItem{
                  Text="sss",Value="ddd"
                 }
                 }
            };

如您所见,两者的型号相同ContactLstModel。现在如何将两者合二为一?

就像在 jQuery 中一样,我们有 $.extend(dest,source);

C# 中是否有等价物?

【问题讨论】:

    标签: c# jquery asp.net .net asp.net-mvc


    【解决方案1】:

    在 C# 和 .NET 4.5 中没有内置的 $.extend 等效项。

    但是,您可以找到许多尝试在 .NET 中使用 reflection 实现这种行为的示例。还有其他人使用序列化(JSON.NET 等)来实现类似的行为。另一种方法是使用 IOC 容器,例如 Automapper

    这是一个如何使用Automapper IOC 将您的第一个对象合并到第二个对象的示例:

    var expr = Mapper.CreateMap<ContactLstModel, ContactLstModel>().ForMember("ContactType", (conf) => { conf.Ignore(); });
    var merged = Mapper.Map<ContactLstModel, ContactLstModel>(_Contact, _ContactOption);
    

    使用 Automapper,您可以控制如何将每个属性从源映射到目标。

    如果您不想要外部库依赖,并且想要完全控制,您可以使用纯反射方法。

    例如,您可以使用类似于 link 中的 CopyValues 方法的方法,并使用反射将第二个对象属性与第一个对象属性合并。

    CopyValues<ContactLstModel>(_Contact, _ContactOption);
    

    所以这行代码会将第二个对象的 ContactType 属性值复制到第一个对象中。

    CopyValues 使用反射循环遍历对象的属性:

    public static void CopyValues<T>(T target, T source)
    {
        Type t = typeof(T);
    
        var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
    
        foreach (var prop in properties)
        {
            var value = prop.GetValue(source, null);
            if (value != null)
                prop.SetValue(target, value, null);
        }
    }
    

    当然,这并不支持 jquery extend 所做的一切(合并、浅克隆和深层克隆到新对象等),但它可以满足您当前的需求。您可以扩展这些原则并构建更全面的解决方案。

    但是请记住,C# 不像 Javascript 那样是一门语言,在 C# 中进行反射的成本要高得多,而在 Javascript 中,原型的属性可以通过廉价的for-in 迭代列出,或者使用调用 Object.keys()。

    【讨论】:

    • 反射比专用于特定对象的方法(如 Tomas Lycken 的回答)要慢一些,并且控制较少,但它是实现这一目标的最通用方法。
    • 是的。 JQuery 扩展自动合并属性而不指定名称,因此基于反射的方法可能是他能获得的最接近这种功能的方法。
    【解决方案2】:

    您可以使用扩展方法来做到这一点:

    public static class ContactModelExtensions {
        public static ContactModel Extend(this ContactModel first, ContactModel replacement) {
            if (!replacement.ContactsName.IsNullOrEmpty()) // or whatever criteria you want
            {
                first.ContactsName = replacement.ContactsName;
            }
            // similar assignment for all other properties
    
            return first; // since we return the first one, properties not set in override
                          // will be untouched
        }
    }
    

    现在,你可以

    var extendedContact = _Contact.Extend(_ContactOptions);
    

    完成它。

    【讨论】:

    • 很好的命题,而且比反射更快,但是这个具体的例子肯定不会编译,因为“override”是一个保留关键字。我建议对其进行修改。
    • @Richard:谢谢。这就是我在没有测试的情况下输入代码的结果,我猜:P
    【解决方案3】:

    您可以使用一些框架来做到这一点。例如ValueInjecter:

        public class NoNullsInjection : ConventionInjection
        {
            protected override bool Match(ConventionInfo c)
            {
                return c.SourceProp.Name == c.TargetProp.Name
                        && c.SourceProp.Value != null;
            }
        }
    
        class A
        {
            public string a { get; set; }
            public string b { get; set; }
        }
    
        static void Main(string[] args)
        {
            A a1 = new A() { a = "123" };
            A a2 = new A() { b = "456" };
            A c = new A();
    
            c.InjectFrom(new NoNullsInjection(),a1,a2); 
            // "c" now have a="123", b="456"     
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-29
      相关资源
      最近更新 更多