Zwierzak
Zwierzak

Reputation: 686

C# cast object to another type stored in string variable

I have class MyWord and many other classes such as Noun, Idiom etc. that inherits from MyWord.

I store those objects in one list:

List<MyWord> Dictionary;

When I Add new element to the list i do it like this:

var myWord = new MyWord(id, word, definition,type,DateTime.Now.ToShortDateString());
Dictionary.Add(myWord);

As you can see, I put there object MyWord. I would like to be able to create for example Noun object and put in into list, like this:

var myWord = new Noun(id, word, definition, type, DateTime.Now.ToShortDateString());
Dictionary.Add(myWord);

The type parameter is a string, for example "noun". I use this method to get Type based on this string:

    private Type GetFullType(string myType)
    {
        //Returns list of all types that inherit from MyWord class
        var supportedTypes = (AppDomain.CurrentDomain.GetAssemblies()
                            .SelectMany(assembly => assembly.GetTypes())
                            .Where(type => type.IsSubclassOf(typeof(MyWord)))).Select(x => x.FullName).ToList();
        return Type.GetType(supportedTypes.Find(x => x.Contains_SkipWhiteSpacesIgnoreCase(myType)));
    }

Now I don't know how to use the GetFullType() return value to convert MyWord to Noun. Like this:

        Type wordType = GetFullType(type);
        var myWord = new MyWord(id, word, definition, type, DateTime.Now.ToShortDateString());
        Dictionary.Add((wordType)myWord);

I hope I explained myself clearly.

Note that I could use If...else structure to create different objects checking the type variable but it's not an elegant solution. Any better ideas?

Upvotes: 3

Views: 4125

Answers (2)

Ian Mercer
Ian Mercer

Reputation: 39297

You can use Activator.CreateInstance to create an instance of a type. See https://msdn.microsoft.com/en-us/library/wccyzw83(v=vs.110).aspx

var myword = Activator.CreateInstance(wordType);

And then you can set the properties on it using reflection, or by casting it to the base class MyWord.

OR you could use reflection on the wordType to find its constructor and call that.

BUT really, are there that many word types that it's not easier (and a whole lot faster) to maintain a Dictionary<string,Func<string, string, WordType>> where you can look up a word type and get a function that makes one for you from its word and definition values?

wordFactories["noun"](word, definition);

Another alternative is to use Impromptu.Interface from Nuget which can wrap any dynamic object in an interface and have it behave just like that. In my natural language engine for .NET that's what I use to take a word from a database and then wrap it up as, say, an INoun, an IPluralNoun, an IMammal, etc.

Upvotes: 3

BendEg
BendEg

Reputation: 21128

What you try to do is still not possible, becuase if we take a look at this:

Type wordType = GetFullType(type);
var myWord = new MyWord(id, word, definition, type, DateTime.Now.ToShortDateString());
Dictionary.Add((wordType)myWord);

You create an instance of MyWord, which could not be casted in Noun or some thing like that, because it is no type of that. What you can use is Activate.CreateInstance for your purpose. Take a look at it here: Activator.CreateInstance

This static method also allows to take a list of parameter, which will automatically passed to the constructor. But be sure, this use reflection and is always slower than creating instances with the new keyword.

Upvotes: 1

Related Questions