2

I'm creating a method that will use CastleWindsor to try to resolve a type, but use a default type if the component isn't configured (so I don't have to configure everything until I actually want to change the implementation). Here's my method...

public static T ResolveOrUse<T, U>() where U : T
    {
        try
        {
            return container.Resolve<T>();
        }
        catch (ComponentNotFoundException)
        {
            try
            {
                U instance = (U)Activator.CreateInstance(typeof(U).GetType());
                return (T)instance;
            }
            catch(Exception ex)
            {
                throw new InvalidOperationException("IOC Couldn't instantiate a '" + typeof(U) + "' because: " + ex.Message);
            }
        }
    }

When a WebConfigReader is passed in as the default type to use, I get the error "No parameterless constructor defined for this object". Here's my WebConfigReader class...

public class WebConfigReader : IConfigReader
{
    public string TfsUri
    {
        get { return ReadValue<string>("TfsUri"); }
    }

    private T ReadValue<T>(string configKey)
    {
        Type type = typeof(T).GetType();
        return (T)Convert.ChangeType(ConfigurationManager.AppSettings[configKey], type);
    }
}

Since I have no ctor, it should work. I've added a paramless ctor and I've passed in true as the second param to CreateInstance and none of the above worked. I can't figure out what I'm missing. Any thoughts?

4
  • typeof(U).GetType() the GetType() is redundant. Commented Feb 5, 2012 at 2:42
  • WebConfigReader would not compile as is, what does your real code look like? Commented Feb 5, 2012 at 2:44
  • 1
    @Baboon It's not redundant; it's incorrect. typeof(U) returns an object that represents the type U, but the type of that object is System.Type, so the type object returned by the GetType call is the one that represents System.Type, not the one that represents U. Commented Feb 5, 2012 at 2:56
  • @phoog that's what i wanted to say, but it was late at night.. Commented Feb 5, 2012 at 14:08

2 Answers 2

11

typeof(U) will already return the type U represents. Doing the extra GetType() on it will return the type System.Type which doesn't have a default constructor.

So your first code block could be written as:

public static T ResolveOrUse<T, U>() where U : T
{
    try
    {
        return container.Resolve<T>();
    }
    catch (ComponentNotFoundException)
    {
        try
        {
            U instance = (U)Activator.CreateInstance(typeof(U));
            return (T)instance;
        }
        catch(Exception ex)
        {
            throw new InvalidOperationException("IOC Couldn't instantiate a '" + typeof(U) + "' because: " + ex.Message);
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

same exact mistake also in the ReadValue<T>() method - just use typeof(U)
I think the downvote was because you didn't provide an answer. You said what the OP doesn't want, but not what the OP does want.
@M.Babcock: That's my guess, and I was probably right since you edited the post and the downvote went away. In general, though, "don't do X" should be a comment; "do Y instead of X" should be an answer.
5

Since you have a generic type parameter you should just use the generic overload of Activator.CreateInstance

U instance = Activator.CreateInstance<U>();

2 Comments

Do you have any idea why the generic version only supports parameterless constructors?
@Gabe I don't know for sure. But one of it's main purposes is supporting the new() constraint so it only needs to support parameterles ctors. Not being able to specify a constructor with arguments is likely a factor in why CreateInstance can't eiter

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.