Make new object with reflection?

2019-09-18 02:02发布

问题:

I'm not sure if this is possible and after lengthy research I haven't found something conclusive.

I am trying to dynamically create a new object (itself a new Type) from a dictionary. So say I have key and value that key and value will become a property that returns the value. Something that I can use like this:

Sample code

public T getObject(Dictionary<string, string> myDict)
{
 // make a new object type with the keys and values of the dictionary. 
 // sample values in dictionary:
 // id : 112345
 // name: "greg"
 // gender: "m"
 // Eventually also make the interface?
}

// Somewhere else:
var myNewObject = helper.getObject();
// what is expected here is that when I type myNewObject. 
// I get id, name, gender as suggestions
int id = myNewObject.Id;

What is important for me is to get intellisense out of it. So I can type object. and suggestions with all the keys will come out. This way I don't need to know the dictionary in advance in order to access the values (or else I would simply use the dictionary).

I have looked into Clay but it isn't clear to me how to use it to get intellisense as I want it. I also found this post about it.

Additionally I checked ImpromptuInterface but for both the documentation is poor or I can't figure it out.

If this is possible with Clay (it sure seems like it) how could I do it so It can work as a library on other projects that won't reference Clay?

If something is unclear or this is a duplicate don't hesitate to comment.

回答1:

To allow IntelliSense to work, the resulting type must be known at compile-time. So at the time you're working with object, you must know its concrete type (or, at least, a type or interface as concrete as you need - having all the methods and properties you want to access).

It's hard to see what you're actually trying to do, but if you do know the type at compile-time, you can make your helper method generic:

public T GetObject<T>(Dictionary<...> dictionary)

This allows you to specify the type you're expecting at the call site:

var obj = GetObject<SomeType>(dictionary);

If this does not sound reasonable to you, you could also use an explicit cast:

var obj = (SomeType)helper.getObject();

If you don't know the concrete type, you'll at least need to have a common interface (or a base class) you can use. The runtime generated type would then be created to implement this interface. But you'll only ever be able to access the members that are known at compile time. How would the compiler know all the possible keys that could exist in your dictionary at runtime? You're trying to code against some kind of contract - so formalize that contract in an interface (for example), and make the runtime generated type implement this interface.