In C#, is it possible to get an instance of an object based on a string without using Reflection?
For example:
Activator.CreateInstance(Type.GetType(objName));
uses reflection.
Is it possible to replace the classic if\else structure of a factory class with a "string to object" implementation that dosn't use reflection?
I have heard that there is, but I don't see how you would do it without reflection.
There is but it's not a simple solution. Essentially you create a dynamic method and then create a delegate from that and use it.
public static BaseBuilder Create(Type builderType, HttpContextBase httpContext, PathDataDictionary pathData)
{
if (!builderType.IsSubclassOf(baseBuilderType)) return null;
BuilderConstructorDelegate del;
if (builderConstructors.TryGetValue(builderType.FullName, out del))
return del(httpContext, pathData);
DynamicMethod dynamicMethod = new DynamicMethod("CreateBaseBuilderInstance", builderType, constructorMethodArgs, builderType);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Newobj, builderType.GetConstructor(constructorMethodArgs));
ilGenerator.Emit(OpCodes.Ret);
del = (BuilderConstructorDelegate)dynamicMethod.CreateDelegate(typeof(BuilderConstructorDelegate));
builderConstructors.TryAdd(builderType.FullName, del);
return del(httpContext, pathData);
}
Here is some code I use in the Builder for ASP.NET
framework in the BuilderFactory.
If it's not clear in the code, you should know that once you have a delegate then that delete is stored in the dictionary called builderConstructors in the code above. So the next time the factory simply uses the delegate.
In this particular case the class requires two parameters in its constructor. If you're using the default constructor for your classes things are a little simpler.
High Performance Class Factory
Since you're using the dependency-injection tag in your question, Dependency Injection frameworks would typically do this for you. There is always reflection involved, but most of them would have a caching mechanism that prevents any reflection the next time an object is requested. Especially when your type is a concrete type with a default constructor (as you shown in your question) no registration is required. For instance, when using the Simple Service Locator, the request would look like this:
object instance = ServiceLocator.Current.GetInstance(Type.GetType(objName));
When you don't want to use a dependency injection framework, what you can do is generate delegates for the creation of those objects and cache them in a dictionary with objName as key (this is basically what DI frameworks will do). While you can use LCG (as Shiv showed), it has gotten much easier with the new .NET 3.5 Expression trees:
private static Dictionary<string, Func<object>> delegates =
new Dictionary<string, Func<object>>();
public static object CreateObjectByName(string name)
{
if (delegates.ContainsKey(name))
{
return delegates[name]();
}
else
{
Func<object> creator = CreateDelegateFor(Type.GetType(name));
// TODO: Don't forget to make this thread-safe :-)
delegates[name] = creator;
}
}
// .NET Expression tree magic!
private static Func<object> CreateDelegateFor(Type type)
{
var constructor = type.GetConstructors().First();
var newServiceTypeMethod = Expression.Lambda<Func<object>>(
Expression.New(constructor, new Expression[0]),
new ParameterExpression[0]);
return newServiceTypeMethod.Compile();
}
You can use Microsoft.VisualBasic.Interaction.CreateObject, but that only applies to COM objects. (On the plus side, this allows you to create objects on other people's computers.)
Related
Why can I not use dynamic param in an extension method, as in the following code:
public static class Extension
{
public static void ExtMethod(this Program pg, object asdf) {
new Program();
}
}
public class Program
{
static void Main(string[] args)
{
dynamic d = new ExpandoObject();
d.test = "test";
new Program().ExtMethod(d.test);
Extension.ExtMethod(new Program(), d.test);
}
}
new Program().ExtMethod(d.test); is throwing a compile time error.
But Extension.ExtMethod(new Program(), d.test); is not causing any error.
This is by design, and part of the specification. From the ECMA C# 5 standard, section 12.7.6.3:
In a method invocation (ยง12.6.6.2) of one of the forms [...] if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. If expr or any of the args has compile-time type dynamic, extension methods will not apply.
The underlying reason for this is that dynamic binding is intended to give the same result as binding at compile-time would... but for extension methods, that would mean retaining all the using directives at execution time. That would be possible, but I suspect it would be very expensive in terms of invocation performance, and the C# design team decided not to go that way.
You need to cast d.test to an object, in other words write;
new Program().ExtMethod((object)d.test);
Consider the following C# code using MemoryCache to generate a new value for a given key if not already preset in the cache:
private static MemoryCache _memoryCache = new MemoryCache();
public T Apply<T>(string key, Func<T> factory)
{
var expiration ...
var newValue = new Lazy<T>(factory);
var value = (Lazy<T>)_memoryCache.AddOrGetExisting(key, newValue, expiration);
return (value ?? newValue).Value;
}
Consider now this:
var hugeObject = new HugeObject();
return cache.Apply("SomeKey", () =>
{
return hugeObject.GetValue();
});
The factory will be invoked "immediately" after AddOrGetExisting or never, so the question is:
Does the Lazy class clear the reference to the factory delegate after having generated the value (so all the resources used by the factory like, in this case, hugeObject, can be released)?
Looking at the reference source, I believe it does release the factory, and call out why:
// We successfully created and stored the value. At this point, the value factory delegate is
// no longer needed, and we don't want to hold onto its resources.
m_valueFactory = ALREADY_INVOKED_SENTINEL;
There is quite a lot of threading code in there so I'm not sure it does so every time, but you'd hope that if they've realise they need to, they will have done so properly.
I am working with ServiceStack. This library has a method for dependency injection, called Register.
public IRegistration<TService> Register<TService>(TService> instance)
Which you call like this:
Container.Register<IFirstServiceInterface>(new FirstServiceInterfaceImplementation());
Container.Register<ISecondServiceInterface>(new SecondServiceInterfaceImplementation());
Now, I want to create a method which takes the same parameters as Register. In my method however, I would add the passed instance and interface type to an ICollection object, to pass it to ServiceStack's Register method at a later point in time. At the time I want to pass these parameters to ServiceStack, I would simply call:
foreach(var item in dependencyCollection)
{
ServiceStack.Register(item);
//not exactly how you call the Register method, but you get the idea.
}
How would I set up a collection object to achieve the result I'm looking for? I'm having trouble storing both an interface type, and an implementation for it.
It's hard to infer what you're looking for here, but maybe you're looking at some of ServiceStack Funq's IOC late-bound API's? e.g:
container.Register(
new FirstServiceInterfaceImplementation(),
typeof(IFirstServiceInterface));
//or
container.RegisterAutoWiredType(
typeof(FirstServiceInterfaceImplementation),
typeof(IFirstServiceInterface));
In which to use the first API you can use a Dictionary<Type,object>, e.g:
var deps = new Dictionary<Type,object> {
{ typeof(IFirstServiceInterface), new FirstServiceInterfaceImplementation() },
{ typeof(ISecondServiceInterface), new SecondServiceInterfaceImplementation() },
};
Then register like:
foreach (var entry in deps)
{
container.Register(entry.Value, entry.Key);
}
I'm receiving event notifications from web services that trigger event handlers with data regarding what triggered the event. I'm trying to test that once an event handler is called that a, b and c are all called with the proper values. This isn't possible without relying on the web service
My solution is to create converters that convert the EventArgs that are returned to my via the services library (Exchange Web Services) to something my dumb objects can understand without relying on third part services. My issue is that the EventArgs class given to my by the EWS library has an internal constructor so there's no easy way to generate an instance of it with random property values without much work with reflection.
For example, I have a simply interface:
public interface IConverter<TFrom, TTo>
{
TTo Convert(TFrom from);
}
and a simple implementation:
public class NotificationEventArgsConverter : IConverter<NotificationEventArgs, NewNotification>
{
public NewNotification Convert(NotificationEventArgs from)
{
return new NewNotification
{
ItemIds = from.Events.Cast<ItemEvent>().Select(x => x.ItemId.ToString())
};
}
}
Question is how can I generate an instance of NotificationEventArgs with random values. Is there a library for this that I missed in my searches?
The entire goal of this is to emulate if I receive an instance of NotificationEventArgs with the following values then NewNotification should resemble x.
Edit
In the meantime I will simply use typeof(T).GetConstructor().
You might want to take a look at AutoFixture:
AutoFixture makes it easier for developers to do Test-Driven Development by automating non-relevant Test Fixture Setup, allowing the Test Developer to focus on the essentials of each test case.
After doing some decompilation of Microsoft.Exchange.WebServices and playing bit with reflection, you can do it for example like this:
var fixture = new Fixture();
// retrieve internal FolderEvent(EventType, DateTime) ctor
// using FolderEvent class as NotificationEvent is abstract
var notificationEventCtor = typeof(FolderEvent).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[] { typeof(EventType), typeof(DateTime) },
null
);
// generate 10 random events with some help of LINQ and AutoFixture
var trashData = Enumerable
.Range(1, 10)
.Select(i => new object[]
{
fixture.CreateAnonymous<EventType>(),
fixture.CreateAnonymous<DateTime>()
})
.Select(p => notificationEventCtor.Invoke(p))
.Cast<NotificationEvent>()
.ToList();
Code above will generate 10 FolderEvents in a list, ready to pass to NotificationEventArgs constructor (which is internal again, so same code applies):
var notificationEventArgsCtor = typeof(NotificationEventArgs).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[]
{
typeof(StreamingSubscription),
typeof(IEnumerable<NotificationEvent>)
},
null
);
var instance = notificationEventArgsCtor
.Invoke(new object[] { null, trashData });
Take a look at the PrivateObject class (specifically these constructor overloads). It wraps all the reflection work for you and allows you to create objects with non-public constructors, as well as access non-public methods and properties of those objects. You can get the underlying objects via the Target property.
Let's say I have this method:
public static object CallMethod(Delegate method, params object[] args)
{
//more logic
return method.DynamicInvoke(args);
}
This below has worked fine for most scenarios, calling it like so (simple example):
Delegate methodCall = new Func<decimal,decimal>(Math.Ceiling);
object callResult = CallMethod(methodCall, myNumber);
However, I've run into a situation where I need to use this on a method that takes in a 'ref' parameter (WCF service call), which the Func class can not handle.
Delegate methodCall =
new Func<MyService.InputClass, MyService.CallResult>(service.DoWork);
Since I don't have a lot of experience dealing with delegates, what would be the easiest way of creating a delegate for the above method to pass on to mine?
This isn't my application so I don't have an easy way of testing it (I was just asked if I knew of a way of resolving the problem), but does this look like it should work?
Delegate methodCall = new Func<MyService.CallResult>(delegate() { return service.DoWork(ref myInput)});
object callResult = CallMethod(methodCall, null);