0

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.

Jose Luis
  • 3,307
  • 3
  • 36
  • 53
  • For your object to have the properties you want, you need to create a new class that can encapsulate the data. The `object`-class is the base-class, so you cannot implement onto it, without creating a custom object (that is implicitly inheriting from it). If you create a class for this, with public properties, you can use IntelliSense, as it will know which properties (and methods) the class will be containing. [See more here](http://www.dotnetperls.com/class) – Malte R Jul 02 '15 at 10:05
  • by link to _Clay_ they use interfaces for getting intellisence, like: `IPerson lou = people[0]; var fullName = lou.FirstName + " " + lou.LastName;` where `people[0]` your dynamic object – Grundy Jul 02 '15 at 10:05
  • @Grundy yes I see, I guess the question is more how can I make an interface at runtime that can correspond to a dynamic type **also** created at runtime? (with the final goal of the type having intellisense) – Jose Luis Jul 02 '15 at 11:38
  • 1
    @Joze, if intellisense work at _compile-time_, and you create something at _run-time_, you can't get it with intellisense :-) – Grundy Jul 02 '15 at 12:01
  • @Grundy Sorry what I meant was compile time! :O) I get lost sometimes. At runtime I can't use intellisense anyway. – Jose Luis Jul 02 '15 at 12:10
  • @MalteR The object was just an example it could as well be pineapples. I am not referring to the class `object`, my bad I guess. The point of it is creating a new type at **compile time** that can have intellisense. Of course if I create a class manually intellisense will see it, that is just standard procedure. – Jose Luis Jul 02 '15 at 12:13
  • can you provide sample what you mean `creating a new type at compile time that can have intellisense`? – Grundy Jul 02 '15 at 12:16
  • @Grundy A sample? there is one in the question. There is a method that returns an object that isn't defined at compile time, but an object that was dynamically created in that method with a dictionary. The returned object would have intellisense to access its properties which are the keys of the dictionary. – Jose Luis Jul 02 '15 at 12:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82198/discussion-between-grundy-and-joze). – Grundy Jul 02 '15 at 12:29

1 Answers1

5

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.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Would it be possible to make the interface dynamically according to the dictionary and the runtime generated type according to it? – Jose Luis Jul 02 '15 at 11:28
  • @Joze You will always need *some* interface at compile-time. It really isn't clear what you're trying to do. Can you show the *exact* code you're using, and the *exact* thing you expect from IntelliSense? It can be sample code, but please show precisely what you want - precisely enough so that you could accept an answer that solves the sample itself. – Luaan Jul 02 '15 at 13:48
  • I updated the question. I hope that brings some light to what I'm trying to do. – Jose Luis Jul 02 '15 at 14:06
  • @Joze Okay, so for your sample code, you'll have to manually code up the interface for the given properties. Your `getObject` method will return this interface - the type you create dynamically will be marked as implementing that interface (for example, if you're using `TypeBuilder`, just call `builder.AddInterfaceImplementation(typeof(IMyInterface))`). IntelliSense will then show you every member declared in the interface, and you'll get compile-time type checking as usual. – Luaan Jul 02 '15 at 14:14
  • So if I understood correctly, the getObject returns the interface and another method returns the object then I bind them together with TypeBuilder and voilà. How can I make the interface dynamically? In code I mean. I can't manually make an interface file since I don't know the keys in advance. Thanks a lot for your help!! – Jose Luis Jul 02 '15 at 14:26
  • @Joze You have to know the keys in advance, there simply isn't another way. Perhaps you mean that you can have several different interfaces (known in advance) and want the "proper" handling code to be picked at runtime? – Luaan Jul 02 '15 at 14:28
  • I guess that is the crux of the problem. I build the dictionary with data elsewhere that I don't know in advance. In order to make the interfaces it would probably result in hundreds of interface files for each possible object and in that case we might as well make the object itself. The objective is making it all dynamically so we can save us the hassle. At runtime we fetch the data, make the dictionaries, parse the keys, (make the interfaces?), bind the interfaces to the dynamically made objects and return them to someone that needs to use them. – Jose Luis Jul 02 '15 at 14:31
  • 1
    @Joze You still have to have the definitions known if you want to use them in code. Perhaps you could use T4 templates to create the C# types automatically from the key-value input (say, stored in files or some XML or something)? – Luaan Jul 02 '15 at 14:39
  • The T4 templates is not a bad idea. I am checking it right now though it may take me a few days to see if it really is a viable option. It might! – Jose Luis Jul 02 '15 at 14:46