有没有办法将键/值对列表转换为数据传输对象

发布于 2024-08-27 01:37:12 字数 859 浏览 8 评论 0原文

...除了明显的循环列表和肮脏的伟大案例声明之外!

我在脑海中思考了一些 Linq 查询,但似乎没有任何接近的结果。

这是一个 DTO 示例(如果有帮助的话):

    class ClientCompany
    {
      public string Title { get; private set; }
      public string Forenames { get; private set; }
      public string Surname { get; private set; }
      public string EmailAddress { get; private set; }
      public string TelephoneNumber { get; private set; }
      public string AlternativeTelephoneNumber { get; private set; }
      public string Address1 { get; private set; }
      public string Address2 { get; private set; }
      public string TownOrDistrict { get; private set; }
      public string CountyOrState { get; private set; }
      public string PostCode { get; private set; }
    }

恐怕我们无法控制以 KV 对形式获取数据的事实。

虽然每个 KV 对到每个属性都有一个有效的映射,而且我确实提前知道密钥,但它们的命名与 DTO 的名称不同。

...apart from the obvious looping through the list and a dirty great case statement!

I've turned over a few Linq queries in my head but nothing seems to get anywhere close.

Here's the an example DTO if it helps:

    class ClientCompany
    {
      public string Title { get; private set; }
      public string Forenames { get; private set; }
      public string Surname { get; private set; }
      public string EmailAddress { get; private set; }
      public string TelephoneNumber { get; private set; }
      public string AlternativeTelephoneNumber { get; private set; }
      public string Address1 { get; private set; }
      public string Address2 { get; private set; }
      public string TownOrDistrict { get; private set; }
      public string CountyOrState { get; private set; }
      public string PostCode { get; private set; }
    }

We have no control over the fact that we're getting the data in as KV pairs, I'm afraid.

and whilst there is an effective mapping of each KV pair to each property and I do know the keys in advance they're not named the same as the DTO.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

再可℃爱ぅ一点好了 2024-09-03 01:37:13

这是一个优雅、可扩展、可维护且速度极快的解决方案,用于从字典加载 DTO。

创建一个控制台应用程序并添加这两个文件。其余的都是自我记录的。

要点:

  • 简单、简洁且可维护的映射类。
  • 使用动态方法进行有效的对象再水化。

注意:如果您复制了上一个 DynamicProperties.cs,您将需要获取这个。我添加了一个标志以允许生成以前版本中没有的私有设置器。

干杯。

program.cs

using System.Collections.Generic;
using System.Diagnostics;
using Salient.Reflection;

namespace KVDTO
{
    /// <summary>
    /// This is our DTO
    /// </summary>
    public class ClientCompany
    {
        public string Address1 { get; private set; }
        public string Address2 { get; private set; }
        public string AlternativeTelephoneNumber { get; private set; }
        public string CountyOrState { get; private set; }
        public string EmailAddress { get; private set; }
        public string Forenames { get; private set; }
        public string PostCode { get; private set; }
        public string Surname { get; private set; }
        public string TelephoneNumber { get; private set; }
        public string Title { get; private set; }
        public string TownOrDistrict { get; private set; }
    }


    /// <summary>
    /// This is our DTO Map
    /// </summary>
    public sealed class ClientCompanyMapping : KeyValueDtoMap<ClientCompany>
    {
        static ClientCompanyMapping()
        {
            AddMapping("Title", "Greeting");
            AddMapping("Forenames", "First");
            AddMapping("Surname", "Last");
            AddMapping("EmailAddress", "eMail");
            AddMapping("TelephoneNumber", "Phone");
            AddMapping("AlternativeTelephoneNumber", "Phone2");
            AddMapping("Address1", "Address1");
            AddMapping("Address2", "Address2");
            AddMapping("TownOrDistrict", "City");
            AddMapping("CountyOrState", "State");
            AddMapping("PostCode", "Zip");
        }
    }


    internal class Program
    {
        private const string Address1 = "1243 Easy Street";
        private const string CountyOrState = "Az";
        private const string EmailAddress = "[email protected]";
        private const string Forenames = "Sky";
        private const string PostCode = "85282";
        private const string Surname = "Sanders";
        private const string TelephoneNumber = "800-555-1212";
        private const string Title = "Mr.";
        private const string TownOrDistrict = "Tempe";

        private static void Main(string[] args)
        {
            // this represents our input data, some discrepancies
            // introduced to demonstrate functionality of the map

            // the keys differ from the dto property names
            // there are missing properties
            // there are unrecognized properties
            var input = new Dictionary<string, string>
                {
                    {"Greeting", Title},
                    {"First", Forenames},
                    {"Last", Surname},
                    {"eMail", EmailAddress},
                    {"Phone", TelephoneNumber},
                    // missing from this input {"Phone2", ""},
                    {"Address1", Address1},
                    // missing from this input {"Address2", ""},
                    {"City", TownOrDistrict},
                    {"State", CountyOrState},
                    {"Zip", PostCode},
                    {"SomeOtherFieldWeDontCareAbout", "qwerty"}
                };


            // rehydration is simple and FAST

            // instantiate a map. You could store instances in a dictionary
            // but it is not really necessary for performance as all of the
            // work is done in the static constructors, so no matter how many
            // times you 'new' a map, it is only ever built once.

            var map = new ClientCompanyMapping();

            // do the work. 
            ClientCompany myDto = map.Load(input);





            // test
            Debug.Assert(myDto.Address1 == Address1, "Address1");
            Debug.Assert(myDto.Address2 == null, "Address2");
            Debug.Assert(myDto.AlternativeTelephoneNumber == null, "AlternativeTelephoneNumber");
            Debug.Assert(myDto.CountyOrState == CountyOrState, "CountyOrState");
            Debug.Assert(myDto.EmailAddress == EmailAddress, "EmailAddress");
            Debug.Assert(myDto.Forenames == Forenames, "Forenames");
            Debug.Assert(myDto.PostCode == PostCode, "PostCode");
            Debug.Assert(myDto.Surname == Surname, "Surname");
            Debug.Assert(myDto.TelephoneNumber == TelephoneNumber, "TelephoneNumber");
            Debug.Assert(myDto.Title == Title, "Title");
            Debug.Assert(myDto.TownOrDistrict == TownOrDistrict, "TownOrDistrict");
        }
    }

    /// <summary>
    /// Base mapper class.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class KeyValueDtoMap<T> where T : class, new()
    {
        private static readonly List<DynamicProperties.Property> Props;
        private static readonly Dictionary<string, string> KvMap;

        static KeyValueDtoMap()
        {
            // this property collection is built only once
            Props = new List<DynamicProperties.Property>(DynamicProperties.CreatePropertyMethods(typeof(T)));
            KvMap=new Dictionary<string, string>();
        }

        /// <summary>
        /// Adds a mapping between a DTO property and a KeyValue pair
        /// </summary>
        /// <param name="dtoPropertyName">The name of the DTO property</param>
        /// <param name="inputKey">The expected input key</param>
        protected static void AddMapping(string dtoPropertyName,string inputKey)
        {
            KvMap.Add(dtoPropertyName,inputKey);
        }

        /// <summary>
        /// Creates and loads a DTO from a Dictionary
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public T Load(Dictionary<string, string> input)
        {
            var result = new T();
            Props.ForEach(p =>
                {
                    string inputKey = KvMap[p.Info.Name];
                    if (input.ContainsKey(inputKey))
                    {
                        p.Setter.Invoke(result, input[inputKey]);
                    }
                });
            return result;
        }
    }
}

DynamicProperties.cs

/*!
 * Project: Salient.Reflection
 * File   : DynamicProperties.cs
 * http://spikes.codeplex.com
 *
 * Copyright 2010, Sky Sanders
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * See LICENSE.TXT
 * Date: Sat Mar 28 2010 
 */

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace Salient.Reflection
{
    /// <summary>
    /// Gets IL setters and getters for a property.
    /// </summary>
    public static class DynamicProperties
    {
        #region Delegates

        public delegate object GenericGetter(object target);

        public delegate void GenericSetter(object target, object value);

        #endregion

        public static IList<Property> CreatePropertyMethods(Type T)
        {
            var returnValue = new List<Property>();

            foreach (PropertyInfo prop in T.GetProperties())
            {
                returnValue.Add(new Property(prop));
            }
            return returnValue;
        }


        public static IList<Property> CreatePropertyMethods<T>()
        {
            var returnValue = new List<Property>();

            foreach (PropertyInfo prop in typeof (T).GetProperties())
            {
                returnValue.Add(new Property(prop));
            }
            return returnValue;
        }


        /// <summary>
        /// Creates a dynamic setter for the property
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        /// <source>
        /// http://jachman.wordpress.com/2006/08/22/2000-faster-using-dynamic-method-calls/
        /// </source>
        public static GenericSetter CreateSetMethod(PropertyInfo propertyInfo)
        {
            /*
            * If there's no setter return null
            */
            MethodInfo setMethod = propertyInfo.GetSetMethod(true);
            if (setMethod == null)
                return null;

            /*
            * Create the dynamic method
            */
            var arguments = new Type[2];
            arguments[0] = arguments[1] = typeof (object);

            var setter = new DynamicMethod(
                String.Concat("_Set", propertyInfo.Name, "_"),
                typeof (void), arguments, propertyInfo.DeclaringType);
            ILGenerator generator = setter.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
            generator.Emit(OpCodes.Ldarg_1);

            if (propertyInfo.PropertyType.IsClass)
                generator.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
            else
                generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);

            generator.EmitCall(OpCodes.Callvirt, setMethod, null);
            generator.Emit(OpCodes.Ret);

            /*
            * Create the delegate and return it
            */
            return (GenericSetter) setter.CreateDelegate(typeof (GenericSetter));
        }


        /// <summary>
        /// Creates a dynamic getter for the property
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        /// <source>
        /// http://jachman.wordpress.com/2006/08/22/2000-faster-using-dynamic-method-calls/
        /// </source>
        public static GenericGetter CreateGetMethod(PropertyInfo propertyInfo)
        {
            /*
            * If there's no getter return null
            */
            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
            if (getMethod == null)
                return null;

            /*
            * Create the dynamic method
            */
            var arguments = new Type[1];
            arguments[0] = typeof (object);

            var getter = new DynamicMethod(
                String.Concat("_Get", propertyInfo.Name, "_"),
                typeof (object), arguments, propertyInfo.DeclaringType);
            ILGenerator generator = getter.GetILGenerator();
            generator.DeclareLocal(typeof (object));
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
            generator.EmitCall(OpCodes.Callvirt, getMethod, null);

            if (!propertyInfo.PropertyType.IsClass)
                generator.Emit(OpCodes.Box, propertyInfo.PropertyType);

            generator.Emit(OpCodes.Ret);

            /*
            * Create the delegate and return it
            */
            return (GenericGetter) getter.CreateDelegate(typeof (GenericGetter));
        }

        #region Nested type: Property

        public class Property
        {
            public GenericGetter Getter;
            public PropertyInfo Info;
            public GenericSetter Setter;

            public Property(PropertyInfo info)
            {
                Info = info;
                Setter = CreateSetMethod(info);
                Getter = CreateGetMethod(info);
            }
        }

        #endregion
    }
}

Here is an elegant, extensible, maintainable and blazingly fast solution for loading DTOs from Dictionaries.

Create a console app and add these two files. The rest is self documenting.

The salient points:

  • simple, brief and maintainable mapping classes.
  • efficient object rehydration using dynamic methods.

NOTE: If you copied the previous DynamicProperties.cs, you will want to get this one. I added a flag to allow generation of private setters that was not in the previous version.

Cheers.

program.cs

using System.Collections.Generic;
using System.Diagnostics;
using Salient.Reflection;

namespace KVDTO
{
    /// <summary>
    /// This is our DTO
    /// </summary>
    public class ClientCompany
    {
        public string Address1 { get; private set; }
        public string Address2 { get; private set; }
        public string AlternativeTelephoneNumber { get; private set; }
        public string CountyOrState { get; private set; }
        public string EmailAddress { get; private set; }
        public string Forenames { get; private set; }
        public string PostCode { get; private set; }
        public string Surname { get; private set; }
        public string TelephoneNumber { get; private set; }
        public string Title { get; private set; }
        public string TownOrDistrict { get; private set; }
    }


    /// <summary>
    /// This is our DTO Map
    /// </summary>
    public sealed class ClientCompanyMapping : KeyValueDtoMap<ClientCompany>
    {
        static ClientCompanyMapping()
        {
            AddMapping("Title", "Greeting");
            AddMapping("Forenames", "First");
            AddMapping("Surname", "Last");
            AddMapping("EmailAddress", "eMail");
            AddMapping("TelephoneNumber", "Phone");
            AddMapping("AlternativeTelephoneNumber", "Phone2");
            AddMapping("Address1", "Address1");
            AddMapping("Address2", "Address2");
            AddMapping("TownOrDistrict", "City");
            AddMapping("CountyOrState", "State");
            AddMapping("PostCode", "Zip");
        }
    }


    internal class Program
    {
        private const string Address1 = "1243 Easy Street";
        private const string CountyOrState = "Az";
        private const string EmailAddress = "[email protected]";
        private const string Forenames = "Sky";
        private const string PostCode = "85282";
        private const string Surname = "Sanders";
        private const string TelephoneNumber = "800-555-1212";
        private const string Title = "Mr.";
        private const string TownOrDistrict = "Tempe";

        private static void Main(string[] args)
        {
            // this represents our input data, some discrepancies
            // introduced to demonstrate functionality of the map

            // the keys differ from the dto property names
            // there are missing properties
            // there are unrecognized properties
            var input = new Dictionary<string, string>
                {
                    {"Greeting", Title},
                    {"First", Forenames},
                    {"Last", Surname},
                    {"eMail", EmailAddress},
                    {"Phone", TelephoneNumber},
                    // missing from this input {"Phone2", ""},
                    {"Address1", Address1},
                    // missing from this input {"Address2", ""},
                    {"City", TownOrDistrict},
                    {"State", CountyOrState},
                    {"Zip", PostCode},
                    {"SomeOtherFieldWeDontCareAbout", "qwerty"}
                };


            // rehydration is simple and FAST

            // instantiate a map. You could store instances in a dictionary
            // but it is not really necessary for performance as all of the
            // work is done in the static constructors, so no matter how many
            // times you 'new' a map, it is only ever built once.

            var map = new ClientCompanyMapping();

            // do the work. 
            ClientCompany myDto = map.Load(input);





            // test
            Debug.Assert(myDto.Address1 == Address1, "Address1");
            Debug.Assert(myDto.Address2 == null, "Address2");
            Debug.Assert(myDto.AlternativeTelephoneNumber == null, "AlternativeTelephoneNumber");
            Debug.Assert(myDto.CountyOrState == CountyOrState, "CountyOrState");
            Debug.Assert(myDto.EmailAddress == EmailAddress, "EmailAddress");
            Debug.Assert(myDto.Forenames == Forenames, "Forenames");
            Debug.Assert(myDto.PostCode == PostCode, "PostCode");
            Debug.Assert(myDto.Surname == Surname, "Surname");
            Debug.Assert(myDto.TelephoneNumber == TelephoneNumber, "TelephoneNumber");
            Debug.Assert(myDto.Title == Title, "Title");
            Debug.Assert(myDto.TownOrDistrict == TownOrDistrict, "TownOrDistrict");
        }
    }

    /// <summary>
    /// Base mapper class.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class KeyValueDtoMap<T> where T : class, new()
    {
        private static readonly List<DynamicProperties.Property> Props;
        private static readonly Dictionary<string, string> KvMap;

        static KeyValueDtoMap()
        {
            // this property collection is built only once
            Props = new List<DynamicProperties.Property>(DynamicProperties.CreatePropertyMethods(typeof(T)));
            KvMap=new Dictionary<string, string>();
        }

        /// <summary>
        /// Adds a mapping between a DTO property and a KeyValue pair
        /// </summary>
        /// <param name="dtoPropertyName">The name of the DTO property</param>
        /// <param name="inputKey">The expected input key</param>
        protected static void AddMapping(string dtoPropertyName,string inputKey)
        {
            KvMap.Add(dtoPropertyName,inputKey);
        }

        /// <summary>
        /// Creates and loads a DTO from a Dictionary
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public T Load(Dictionary<string, string> input)
        {
            var result = new T();
            Props.ForEach(p =>
                {
                    string inputKey = KvMap[p.Info.Name];
                    if (input.ContainsKey(inputKey))
                    {
                        p.Setter.Invoke(result, input[inputKey]);
                    }
                });
            return result;
        }
    }
}

DynamicProperties.cs

/*!
 * Project: Salient.Reflection
 * File   : DynamicProperties.cs
 * http://spikes.codeplex.com
 *
 * Copyright 2010, Sky Sanders
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * See LICENSE.TXT
 * Date: Sat Mar 28 2010 
 */

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace Salient.Reflection
{
    /// <summary>
    /// Gets IL setters and getters for a property.
    /// </summary>
    public static class DynamicProperties
    {
        #region Delegates

        public delegate object GenericGetter(object target);

        public delegate void GenericSetter(object target, object value);

        #endregion

        public static IList<Property> CreatePropertyMethods(Type T)
        {
            var returnValue = new List<Property>();

            foreach (PropertyInfo prop in T.GetProperties())
            {
                returnValue.Add(new Property(prop));
            }
            return returnValue;
        }


        public static IList<Property> CreatePropertyMethods<T>()
        {
            var returnValue = new List<Property>();

            foreach (PropertyInfo prop in typeof (T).GetProperties())
            {
                returnValue.Add(new Property(prop));
            }
            return returnValue;
        }


        /// <summary>
        /// Creates a dynamic setter for the property
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        /// <source>
        /// http://jachman.wordpress.com/2006/08/22/2000-faster-using-dynamic-method-calls/
        /// </source>
        public static GenericSetter CreateSetMethod(PropertyInfo propertyInfo)
        {
            /*
            * If there's no setter return null
            */
            MethodInfo setMethod = propertyInfo.GetSetMethod(true);
            if (setMethod == null)
                return null;

            /*
            * Create the dynamic method
            */
            var arguments = new Type[2];
            arguments[0] = arguments[1] = typeof (object);

            var setter = new DynamicMethod(
                String.Concat("_Set", propertyInfo.Name, "_"),
                typeof (void), arguments, propertyInfo.DeclaringType);
            ILGenerator generator = setter.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
            generator.Emit(OpCodes.Ldarg_1);

            if (propertyInfo.PropertyType.IsClass)
                generator.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
            else
                generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);

            generator.EmitCall(OpCodes.Callvirt, setMethod, null);
            generator.Emit(OpCodes.Ret);

            /*
            * Create the delegate and return it
            */
            return (GenericSetter) setter.CreateDelegate(typeof (GenericSetter));
        }


        /// <summary>
        /// Creates a dynamic getter for the property
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        /// <source>
        /// http://jachman.wordpress.com/2006/08/22/2000-faster-using-dynamic-method-calls/
        /// </source>
        public static GenericGetter CreateGetMethod(PropertyInfo propertyInfo)
        {
            /*
            * If there's no getter return null
            */
            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
            if (getMethod == null)
                return null;

            /*
            * Create the dynamic method
            */
            var arguments = new Type[1];
            arguments[0] = typeof (object);

            var getter = new DynamicMethod(
                String.Concat("_Get", propertyInfo.Name, "_"),
                typeof (object), arguments, propertyInfo.DeclaringType);
            ILGenerator generator = getter.GetILGenerator();
            generator.DeclareLocal(typeof (object));
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
            generator.EmitCall(OpCodes.Callvirt, getMethod, null);

            if (!propertyInfo.PropertyType.IsClass)
                generator.Emit(OpCodes.Box, propertyInfo.PropertyType);

            generator.Emit(OpCodes.Ret);

            /*
            * Create the delegate and return it
            */
            return (GenericGetter) getter.CreateDelegate(typeof (GenericGetter));
        }

        #region Nested type: Property

        public class Property
        {
            public GenericGetter Getter;
            public PropertyInfo Info;
            public GenericSetter Setter;

            public Property(PropertyInfo info)
            {
                Info = info;
                Setter = CreateSetMethod(info);
                Getter = CreateGetMethod(info);
            }
        }

        #endregion
    }
}
绮烟 2024-09-03 01:37:13

如果您可以使数据看起来像 ['Title':'Mr', 'Forenames':'John', 'Surname':'Doe',...],那么您应该能够将 kvp JSON 反序列化为源对象。

If you can get the data to look like ['Title':'Mr', 'Forenames':'John', 'Surname':'Doe',...], then you should be able to JSON deserialize the kvp into your source object.

给我一枪 2024-09-03 01:37:13

在这种情况下,我将使用反射将键值对映射到对象属性。例如,请检查此SO问题的已接受答案

In such a case, I would use reflection to map the Key-Value pairs to the object properties. For an example, check the accepted answer on this SO question

挽梦忆笙歌 2024-09-03 01:37:13

或者,如果您不想进行反射,您可以使用它(这不会工作得非常快):

var ccd = new List<KeyValuePair<string, string>>();
ccd.Add(new KeyValuePair<string, string>("Title", ""));
ccd.Add(new KeyValuePair<string, string>("Forenames", ""));
ccd.Add(new KeyValuePair<string, string>("Surname", ""));
ccd.Add(new KeyValuePair<string, string>("EmailAddress", ""));
ccd.Add(new KeyValuePair<string, string>("TelephoneNumber", ""));
ccd.Add(new KeyValuePair<string, string>("AlternativeTelephoneNumber", ""));
ccd.Add(new KeyValuePair<string, string>("Address1", ""));
ccd.Add(new KeyValuePair<string, string>("Address2", ""));
ccd.Add(new KeyValuePair<string, string>("TownOrDistrict", ""));
ccd.Add(new KeyValuePair<string, string>("CountyOrState", ""));
ccd.Add(new KeyValuePair<string, string>("PostCode", ""));

var data = new List<List<KeyValuePair<string, string>>> { ccd, ccd, ccd };

var companies = from d in data
                select new ClientCompany {
                    Title = d.FirstOrDefault(k => k.Key == "Title").Value,
                    Forenames = d.FirstOrDefault(k => k.Key == "Forenames").Value,
                    Surname = d.FirstOrDefault(k => k.Key == "Surname").Value,
                    EmailAddress = d.FirstOrDefault(k => k.Key == "EmailAddress").Value,
                    TelephoneNumber = d.FirstOrDefault(k => k.Key == "TelephoneNumber").Value,
                    AlternativeTelephoneNumber = d.FirstOrDefault(k => k.Key == "AlternativeTelephoneNumber").Value,
                    Address1 = d.FirstOrDefault(k => k.Key == "Address1").Value,
                    Address2 = d.FirstOrDefault(k => k.Key == "Address2").Value,
                    TownOrDistrict = d.FirstOrDefault(k => k.Key == "TownOrDistrict").Value,
                    CountyOrState = d.FirstOrDefault(k => k.Key == "CountyOrState").Value,
                    PostCode = d.FirstOrDefault(k => k.Key == "PostCode").Value,
                };

Alternatively if you don't want to go with reflection you could use this (this wont' work blazingly fast):

var ccd = new List<KeyValuePair<string, string>>();
ccd.Add(new KeyValuePair<string, string>("Title", ""));
ccd.Add(new KeyValuePair<string, string>("Forenames", ""));
ccd.Add(new KeyValuePair<string, string>("Surname", ""));
ccd.Add(new KeyValuePair<string, string>("EmailAddress", ""));
ccd.Add(new KeyValuePair<string, string>("TelephoneNumber", ""));
ccd.Add(new KeyValuePair<string, string>("AlternativeTelephoneNumber", ""));
ccd.Add(new KeyValuePair<string, string>("Address1", ""));
ccd.Add(new KeyValuePair<string, string>("Address2", ""));
ccd.Add(new KeyValuePair<string, string>("TownOrDistrict", ""));
ccd.Add(new KeyValuePair<string, string>("CountyOrState", ""));
ccd.Add(new KeyValuePair<string, string>("PostCode", ""));

var data = new List<List<KeyValuePair<string, string>>> { ccd, ccd, ccd };

var companies = from d in data
                select new ClientCompany {
                    Title = d.FirstOrDefault(k => k.Key == "Title").Value,
                    Forenames = d.FirstOrDefault(k => k.Key == "Forenames").Value,
                    Surname = d.FirstOrDefault(k => k.Key == "Surname").Value,
                    EmailAddress = d.FirstOrDefault(k => k.Key == "EmailAddress").Value,
                    TelephoneNumber = d.FirstOrDefault(k => k.Key == "TelephoneNumber").Value,
                    AlternativeTelephoneNumber = d.FirstOrDefault(k => k.Key == "AlternativeTelephoneNumber").Value,
                    Address1 = d.FirstOrDefault(k => k.Key == "Address1").Value,
                    Address2 = d.FirstOrDefault(k => k.Key == "Address2").Value,
                    TownOrDistrict = d.FirstOrDefault(k => k.Key == "TownOrDistrict").Value,
                    CountyOrState = d.FirstOrDefault(k => k.Key == "CountyOrState").Value,
                    PostCode = d.FirstOrDefault(k => k.Key == "PostCode").Value,
                };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文