Christian Ruppert
Christian Ruppert

Reputation: 3779

Strongly typed object from string type name (C#)

if you take a look at the following code, you will (hopefully) see what I am trying to archieve. Basically this code does:

Not very elegant is, of course, the pseudo-switch case, which I would have to update for all different criteria I create.

So, my question, is there a "generic" way to create an instance which is strongly typed using a string as "source" for the type.

I know I can use Reflection to create an instance, but this is of type object, so I would not be able to add it to the list. Oh, just got an idea... Create object using reflection, cast it to supertype (SearchCrit), add to list. Real type should still be the "correct subtype" I hope...

Will try it, and update this post with results. Any better ideas?

Chris

   private IList<SearchCriteria> _searchCriteriaAll;
    public IList<SearchCriteria> SearchCriteriaAll
    {
        get
        {
            if (_searchCriteriaAll == null)
            {
                _searchCriteriaAll = new List<SearchCriteria>();
                var tN = typeof (SearchCriteria).ToString();
                foreach (var o in DataStorage.LinkedObjects)
                {
                    if (tN.StartsWith(o.TypeName))
                    {
                        if (o.TypeName == typeof(StringSearchCriteria).ToString())
                            _searchCriteriaAll.Add(new StringSearchCriteria(o));
                    }
                }
            }
            return _searchCriteriaAll;
        }
    }

EDIT:

Thanks for the tips, the "correct" way would definitly be the factory pattern. I will look into that. For now, I use this hack, because the subclasses are so small, I dont want a factory for each one.. (and this place is currently the only one with such a "fancy" feature)

   private IList<SearchCriteria> _searchCriteriaAll;
    public IList<SearchCriteria> SearchCriteriaAll
    {
        get
        {
            if (_searchCriteriaAll == null)
            {
                _searchCriteriaAll = new List<SearchCriteria>();
                var tN = typeof (SearchCriteria).ToString();
                foreach (var o in DataStorage.LinkedObjects)
                {
                    if (tN.StartsWith(o.TypeName))
                    {
                        var newO = Activator.CreateInstance(typeof(SearchCriteria).Assembly.FullName, o.TypeName);
                        var newCrit = newO.Unwrap() as SearchCriteria;
                        newCrit.DataStorage = o;
                        _searchCriteriaAll.Add(newCrit);
                    }
                }
            }
            return _searchCriteriaAll;
        }
    }

Upvotes: 4

Views: 3706

Answers (3)

Marc Gravell
Marc Gravell

Reputation: 1064324

Generics and reflection don't make good friends. A simpler approach here is to use the non-generic list interface:

_searchCriteriaAll = new List<SearchCriteria>();
IList list = (IList) _searchCriteriaAll;
...
Type type = typeof(SearchCriteria).Assembly.GetType(o.TypeName);
list.Add(Activator.CreateInstance(type));

(where o.TypeName includes the namespace information, but doesn't have to be assembly-qualified)

This is still runtime type-safe (it'll throw at runtime if it is wrong), and still adjusts the same list.

Note also that we only look inside Assembly directly via Assembly.GetType().

Upvotes: 3

Mark Seemann
Mark Seemann

Reputation: 233505

It's not entirely clear to me what you are trying to achieve, but you can create a Type from a string like this:

var t = Type.GetType(typeName);

If you want to examine whether it's a proper subtype, you can use the IsAssignableFrom method.

Upvotes: 0

Aaronaught
Aaronaught

Reputation: 122684

I'd say you're looking for the Factory Method Pattern.

There's a C# sample here - the first link explains the pattern better, the second is the right language for you.

Upvotes: 0

Related Questions