如何基于另一个创建新对象?

时间:2016-09-08 17:46:52

标签: c# object properties creation

我有一些没用的对象,比方说,30个属性。其中一半对我有用,所以我想创建一个只有我需要的属性的新的有用对象,所以其余部分不占用对象可视化器中的空间。我不想定义新类并输入它们。我想要像

这样的东西
var list = new List<SomeType> { usefulProp1, usefulProp2, ... };
var usefulObject = new NewItem(notUsefulObject, list);

其中SomeType不是字符串(列表不包含属性名称)。

3 个答案:

答案 0 :(得分:1)

如果它是永久性的,那么正确地执行它将是创建一个继承自基类的类,并仅填充所需的属性。

public UsefulObject : NotUsefulObject 
{
    public int MyProperty 
    {
       get
       {
          return base.MyProperty; // this is arbitrary you can do it however you want.
       }
       set
       {
          MyProperty = value;
       }
    }
}

然后,您可以根据需要重复使用有用的对象。

var list = new List<UsefulObject>();

答案 1 :(得分:1)

var list = new List<Expression<Func<object>>> { () => notUsefulObject.usefulProp1, () => notUsefulObject.usefulProp2... };
var nm = new AssemblyName("MyDynamicAssembly");
TypeBuilder tb = Thread.GetDomain().DefineDynamicAssembly(nm, AssemblyBuilderAccess.RunAndSave).DefineDynamicModule(nm.Name, nm.Name + ".dll").DefineType("NewItem", TypeAttributes.Public);
const MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
foreach (Expression b in list.Select(x => x.Body))
{
    MemberInfo mi = ((MemberExpression)b).Member;
    Type t = b.Type;
    FieldBuilder fb = tb.DefineField(mi.Name.ToLower(), t, FieldAttributes.Private);
    PropertyBuilder pb = tb.DefineProperty(mi.Name, PropertyAttributes.HasDefault, t, null);
    MethodBuilder getBld = tb.DefineMethod("get_" + mi.Name, GetSetAttr, t, Type.EmptyTypes);
    ILGenerator getGen = getBld.GetILGenerator();
    getGen.Emit(OpCodes.Ldarg_0);
    getGen.Emit(OpCodes.Ldfld, fb);
    getGen.Emit(OpCodes.Ret);
    MethodBuilder setBld = tb.DefineMethod("set_" + mi.Name, GetSetAttr, null, new[] { t });
    ILGenerator setGen = setBld.GetILGenerator();
    setGen.Emit(OpCodes.Ldarg_0);
    setGen.Emit(OpCodes.Ldarg_1);
    setGen.Emit(OpCodes.Stfld, fb);
    setGen.Emit(OpCodes.Ret);
    pb.SetGetMethod(getBld);
    pb.SetSetMethod(setBld);
}
object usefulObject = Activator.CreateInstance(tb.CreateType());

答案 2 :(得分:0)

因为您说这个问题特定于对象可视化器,所以最好的解决方案是为可以用作代理的类创建Debugger Type Proxy

[DebuggerTypeProxy(typeof(SomeTypeDebugView))]
public class SomeType
{
    public string Foo { get; set; }
    public string Bar { get; set; }

    internal class SomeTypeDebugView
    {
        private SomeType _someType;

        public SomeTypeDebugView(SomeType someType)
        {
            _someType = someType;
        }

        public string Foo { get { return _someType.Foo; } }
    }
}

class Program
{
    static void Main()
    {
        var someType = new SomeType();
        someType.Foo = "foo";
        someType.Bar = "bar";

        Debugger.Break();
    }
}

除非您选择查看“原始类型”,否则这将导致Bar默认隐藏在调试可视化工具中

enter image description here

如果您正在寻找更多的一次性调试类型,您可以使用annonamous类型在观察窗口中创建所需的新类型,例如他的new {Foo = someType.Foo, Bar = someType.Bar }

enter image description here

这也可以与LINQ一起使用来执行IEnumerable上的选择,例如someTypeList.Select(x=> new {Foo = x.Foo, Bar = x.Bar})

enter image description here