How to convert object returned by Activator.CreateInstance to the type it converted?
In the code below, is it possible to convert x to the type you're passing into Activator.CreateInstance
without knowing what it is ahead of 开发者_如何学Pythontime? I tried passing in typeof...
but that doesn't work.
var testClasses = AppDomain.CurrentDomain.GetAssemblies()
.Single(a=>a.FullName.StartsWith("VerifyStuff")).GetTypes()
.Where(t=>t.UnderlyingSystemType.Name.StartsWith("VerifyXXX"));
var x = Activator.CreateInstance(testClasses.ElementAt(0));
Thanks!
You simply need to cast it:
MyObject x = (MyObject) Activator.CreateInstance(testClasses.ElementAt(0));
of course this is going to be more difficult if you have a whole range of types in testClasses
. If they are all derived from the same base class or implement the same interface then you can cast to that base class or interface.
Edit:
is it possible to convert x to the type you're passing into Activator.CreateInstance without knowing what it is ahead of time?
just to be a little more explanatory: x is of the type you passed in to CreateInstance
, but it is cast as an object, because CreateInstance has no idea what you may throw at it. You problem occurs after you've created your concrete instance - you can't pass it into another (strongly typed) function because you have it as an object
. There are a couple of ways around this:
as i mentioned above, have them all derive from the same base class or interface, so that you can pass them around as that base class or interface type
if you have a function that needs to perform an operation on those concrete instances, create a generic function to do it:
public T MyFunc(T myConcreteInstance) { ... do whatever it is i need to do... }
this is ugly, but it may be difficult to avoid... use a big if..else if statement to determine their types before operating on them (hint: to avoid this use option #1 above...):
Type t = myConcreteInstance.GetType(); if (t == typeof(someType1)) { } else if (t == typeof(someType2)) { } ... etc ...
If at this point you are thinking "why don't i just make a generic version of CreateInstance()?" then don't bother - there already is one, it still doesn't solve your issue of having things strongly typed before passing them around. To quote MSDN:
In general, there is no use for the CreateInstance in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used (new operator in C#, New in Visual Basic, gcnew in C++).
If you are going to use CreateInstance, it's because you don't know the type ahead of time, therefore you must work around it.
From @slugster's answer:
If you are going to use CreateInstance, it's because you don't know the type ahead of time, therefore you must work around it.
For people reading this an alternative strategy to this:
var x = Activator.CreateInstance(testClasses.ElementAt(0));
and working out the type:
Type t = myConcreteInstance.GetType();
if (t == typeof(someType1))
{
}
else if (t == typeof(someType2))
{
}
In my situation I'm using Mediatr & I can't Cast the TResponse to a concrete implementation, instead I resort to a common Interface. In this example I show a ICommonResult that all Generic CommonResult<T's> implement that are passed in as the TResponse. This is how you can get around a long if, elseif
or switch
type check, eg:
protected override void Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state)
{
// Keep a look out, there's only one example on the internet including GitHub Search: https://cs.github.com/?scopeName=All+repos&scope=&q=language%3Acsharp+%22Handle%28TRequest+request%2C+TException+exception%2C+RequestExceptionHandlerState%3CTResponse%3E+state%29%22
// and my code here is way better than the one other example: https://github.com/paulopiriquito/SampleMediator/blob/915e82ac249b6e366df030c9f8456a6d809c2353/Behaviours/RequestExceptionHandler.cs?q=language%3Acsharp+%22Handle%28TRequest+request%2C+TException+exception%2C+RequestExceptionHandlerState%3CTResponse%3E+state%29%22
var response = Activator.CreateInstance<TResponse>() as ICommonResult;
// PII Protection
Redactor.Redact(request!);
var pairs = JObject.FromObject(request)
.Descendants()
.OfType<JProperty>()
.Where(p => p.Value is JValue)
.Select(p => p.Name + ":" + p.Value);
string requestNameAndArgsWithValues = $"{typeof(TRequest).Name}({string.Join(",", pairs)})";
if (response != null)
{
response.AddError(ExceptionHelper.GetCommonErrorFromException(exception));
response.IsException = true;
}
_logger.LogCritical($"Description: Exception handler Method: {requestNameAndArgsWithValues} Errors: {commonError.Description} User: {_userService.ToString()}");
);
state.SetHandled((TResponse)response!);
}}
The Interface:
public interface ICommonResult
{
public bool IsSuccess { get; }
public bool IsException { get; set; }
void AddError(CommonError commonError);
}
精彩评论