Activator.CreateInstance and Ninject - c#

I have a project I'm working on where I don't know what class I will need to instantiate at compile time. I'm trying to use Activator.CreateInstance() to generate a new class for me based on the user input. The code below works well, but I had to change my constructor on my INECCQuery classes to only have a default constructor and not use any sort of dependency injection. Is there a way I can still use my injection bindings and the Activator.CreatInstance()? I'm using Ninject for injection.
[HttpGet]
public ActionResult Index(string item) {
Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper()));
if (t != null) {
INECCQuery query = (INECCQuery)Activator.CreateInstance(t);
var results = query.Check();
return View("Index", results);
}
return View("Notfound");
}

Constructor injection is always preferred where possible, but a suitable backup would be to leverage property injection.
http://ninject.codeplex.com/wikipage?title=Injection%20Patterns
class SomeController {
[Inject]
public Object InjectedProperty { get; set; }
}
Based on the assumption that you are trying to replace the Activator.CreateInstance you can inject a Func<T, INECCQuery> or whatever factory you wish to use.

You can get Ninject to give you an object of type t at runtime and still get the dependency injection via the constructor.... I do something similar for one case within my application.
In the Global.asax.cs file, I have the following method:
/// <summary>
/// Gets the instance of Type T from the Ninject Kernel
/// </summary>
/// <typeparam name="T">The Type which is requested</typeparam>
/// <returns>An instance of Type T from the Kernel</returns>
public static T GetInstance<T>()
{
return (T)Kernel.Get(typeof(T));
}
This depends on a static Kernel reference.
Then, in code, I do
var myInfrastructureObject = <YourAppNameHere>.GetInstance<MyInfrastructureType>();
So, I know the type at compile time whereas you don't, but it wouldn't be that difficult to change that.
You may also wish to look into the ServiceLocator Pattern.

I've actually found out you can just pass in a second option to the Activator.CreateInstance method and as long as it matches your constructors signature it will work. The only problem is if your parameters don't match you will get a runtime error.
Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper()));
INECCQuery query = (INECCQuery)Activator.CreateInstance(t, repository);
Thanks for all the help.

Related

Static generic delegate field in C#

Using generic types is nice and easy, but since I tried to implement my own generic types, I came to a problem which I couldn't solve by myself yet. I want to have a static field for a delegate. This is how it works for me when using non-generic types:
delegate Type Type_Delegate(Type type);
static Type_Delegate TypeMethod = new Type_Delegate(TypeMethodName);
// Now the TypeMethod can be called like this from somewhere in the Code:
ClassName.TypeMethod(typeof(string));
But when using any generic type:
delegate T Type_Delegate<T>(T type);
// This static field syntax isn't allowed:
static Type_Delegate<T> TypeMethod = new Type_Delegate<T>(TypeMethodName);
// It would be a dream to be able to use it like this now:
ClassName.TypeMethod<string>("Hello world!");
T is unknown type/namespace.
When I experiment with the syntax:
// This static field syntax isn't allowed, too:
static Type_Delegate TypeMethod = new Type_Delegate(TypeMethodName);
Type arguments are missing for usage.
I tried several ideas about the possible syntax, but not succeed...
How do I need to change the static field syntax to work as assumed, so the code is able to set a generic delegate method as value, without having to specify a type at that time?
Edit: I also tried to wrap the delegate and field with a generic static class, but there I still have the same syntax issues, when I want to set the field value without specifying the type.
Edit 2: Maybe the following example workaround apporach will clarify my thoughts more, since I think most commenters didn't understand my goal (maybe it's my bad English, too):
using System;
using System.Linq;
using System.Reflection;
namespace Testing
{
public static class GenericTest
{
public interface IGenericClass<T>
{
T Method(T parameter);
}
public class GenericClass<T> : IGenericClass<T>
{
public T Method(T parameter)
{
// Just a stupid example, don't think about that...
return parameter;
}
}
/// <summary>
/// The value must be any type that implements the IGenericClass<T> interface
/// </summary>
public static Type GenericField = typeof(GenericClass<>);
/// <summary>
/// Call the method of an instance of the type that was set to GenericField
/// </summary>
/// <param name="T">The type to use for creating an instance of the generic class</param>
/// <param name="parameter">The parameter for calling the method of the generic class</param>
/// <returns>Any value of type "T"</returns>
public static dynamic GenericMethod(Type T, object parameter)
{
var genericType = GenericField.MakeGenericType(new Type[] { T });
MethodInfo method = genericType.GetMethod("Method");
if (method == null) throw new InvalidCastException("GenericField isn't a IGenericClass<T> type");
return method.Invoke(Activator.CreateInstance(genericType), new object[] { parameter });
}
}
}
Now I can do something like this somewhere else in the code:
MessageBox.Show(Testing.GenericTest.GenericMethod(typeof(string), "Hello world!"));
In this example solution I need to work with classes and an interface, require reflections, it's a whole bunch of code required to get the same functionality for a generic (class-)method, as I can get with only two lines of code when working with non-generic methods (using delegates). What an overhead, what a hack - I try to avoid doing such nasty things in productive code. But if there are no better 2 lines of Code that do the same, this time I will have to fight my ego...
It is possible, by wrapping it in a generic class definition and using the class type parameter.
static class C<T>
{
public static DelegateTypePrototype<T> DelegateType;
}
This way the type only has to be resolved once you "request" an instance of the class. At least that's my intuitive understanding coming from C++ templates background.

Can Autofac delegate factories pass parameters to nested objects?

I'd like to use an Autofac delegate factory to resolve an object graph where some of the nested objects need to be passed parameters. E.g. If the QuoteService in the Autofac delegate factory example required a url to retrieve data from, or the QuoteService itself had a dependency that required a parameter.
public class WebQuoteService : IQuoteService
{
public WebQuoteService(Uri source)
{
}
}
public class Shareholding
{
public Shareholding(string symbol, uint holding, IQuoteService quoteService)
{
}
}
I'd like to be able to declare and register a delegate like so:
public delegate Owned<Shareholding> ShareholdingFactory(string symbol, uint holding,
Uri source);
builder.RegisterGeneratedFactory<ShareholdingFactory>();
The problem I run into is that Autofac can't resolve the uri parameter of the WebQuoteService.
I've seen a few similar questions & solutions, but nothing particularly neat. Autofac-passing-parameter-to-nested-types suggests registering a lambda to explicitly implement the factory and resolve the nested dependency. I'm sure that would work, but it becomes very messy if the parameter is needed at a deeper level or when there are more dependencies.
The temporary solution I'm using is an improvement on that, resolving the IQuoteService in Shareholding OnPreparing, and forwarding the parameters created by the Autofac generated factory.
builder.RegisterType<Shareholding>().OnPreparing(e =>
{
e.Parameters = e.Parameters.Union(new[]
{
new TypedParameter(typeof (IQuoteService), e.Context.Resolve<IQuoteService>(e.Parameters))
});
});
That works ok and avoids manually resolving other parameters, but I actually need to do it twice to forward the parameters to a second nested level.
I've considered, but not tried to use BeginLifetimeScope(Action<ContainerBuilder>) as suggested by can-components-be-temporarily-registered-in-an-autofac-container. I think I'd have to implement the factory manually, but I could then register the uri so it would work at any nesting level.
What I'd actually like to be able to do is attach to WebQuoteService OnPreparing and access the delegate factory's parameters. Something like this can be made to work with reflection but that's obviously not ideal.
builder.RegisterType<WebQuoteService>().OnPreparing(e =>
{
var parameters = e.Context._context._activationStack.Last().Parameters;
e.Parameters = e.Parameters.Concat(parameters);
});
Can anyone suggest a cleaner alternative to pass parameters to objects nested two levels deep?
Sorry to self-answer, but failing a better suggestion I thought I should document the best solution I have.
In OnPreparing, you can use reflection to access the Autofac activation stack and the parameters passed to the delegate factory. These can then be added to the parameters of the nested component being resolved. This works with any level of nesting (it only needs to be added to OnPreparing for the component that requires parameters.)
Register like so:
builder.RegisterType<WebQuoteService>()
.OnPreparing(AutofacExtensions.ForwardFactoryParameters);
Using this helper class:
public static class AutofacExtensions
{
private static readonly FieldInfo ContextFieldInfo;
private static readonly FieldInfo ActivationStackFieldInfo;
static AutofacExtensions()
{
var autofacAssembly = typeof(IInstanceLookup).Assembly;
Type instanceLookupType = autofacAssembly.GetType("Autofac.Core.Resolving.InstanceLookup");
ContextFieldInfo = instanceLookupType.GetField("_context", BindingFlags.Instance | BindingFlags.NonPublic);
Type resolveOperationType = autofacAssembly.GetType("Autofac.Core.Resolving.ResolveOperation");
ActivationStackFieldInfo = resolveOperationType.GetField("_activationStack", BindingFlags.Instance | BindingFlags.NonPublic);
}
public static IResolveOperation Context(this IInstanceLookup instanceLookup)
{
return (IResolveOperation)ContextFieldInfo.GetValue(instanceLookup);
}
public static IEnumerable<IInstanceLookup> ActivationStack(this IResolveOperation resolveOperation)
{
return (IEnumerable<IInstanceLookup>)ActivationStackFieldInfo.GetValue(resolveOperation);
}
/// <summary>
/// Pass parameters from the top level resolve operation (typically a delegate factory call)
/// to a nested component activation.
/// </summary>
public static void ForwardFactoryParameters(PreparingEventArgs e)
{
var delegateFactoryActivation = ((IInstanceLookup) e.Context).Context().ActivationStack().Last();
e.Parameters = e.Parameters.Concat(delegateFactoryActivation.Parameters);
}
}
From version 6, Matt's answer no longer functions. Below is correct.
public static void ForwardFactoryParameters(PreparingEventArgs e)
{
var ctx = e.Context;
var oper = ctx.GetType().GetProperty("Operation").GetValue(ctx);
var requestStack = oper.GetType().GetProperty("InProgressRequests").GetValue(oper) as SegmentedStack<ResolveRequestContext>;
if (requestStack.Count == 1)
{
//Nothing to do; we are on the first level of the call stack.
return;
}
var entryRequest = requestStack.Last();
e.Parameters = entryRequest.Parameters;
}

Inheriting from System.Data.Common.DbCommand, Parameters property is null

I'm busy building a custom framework for data retrieval and serialization and I'm running into a problem when defining a proprietary database connection/command/parameter combo. Everything works as expected until I try and add parameters to my custom command object. I have a base class that handles query preparation and execution with a generic function as follows:
/// <summary>
/// Prepares a command for execution.
/// </summary>
/// <typeparam name="C">The type of command to prepare</typeparam>
/// <typeparam name="P">The type of parameters to add to the command</typeparam>
/// <param name="query">The query to be prepared for the command</param>
/// <param name="parameters">Dictionary of parameters to be added to the command</param>
/// <returns>A prepared command to execute against a database</returns>
protected virtual C Prepare<C, P>(string query, Dictionary<string, object> parameters)
where C : DbCommand, new()
where P : DbParameter, new()
{
if (Connection == null)
throw new System.Exception("Database connector hasn't been initialized yet. Call .Initialize() first.");
C command = new C()
{
CommandText = query,
Connection = Connection
};
if (parameters != null)
{
foreach (KeyValuePair<string, object> kvp in parameters)
{
command.Parameters.Add(new P() // <-- Breaks right here!
{
ParameterName = kvp.Key,
Value = kvp.Value
});
}
parameters = null;
}
return command;
}
I have classes implemented for most of the provider types (Ole, ADO, ODBC, Oracle, etc), but they are based off the standard .NET types provided in the System.Data namespace. I now have a completely custom class that inherits from System.Data.Common.DbCommand that I want to use, but when I try and add parameters (in the Prepare function above) to this new class, I see the Parameters property of my new class is null! It is inherited from the base class and is set to read only, so I can't initialize it on my own. My class is defined as follows:
public sealed class Connection : System.Data.Common.DbConnection
I've tried explicitly overriding the property in my class as public new List<Parameter> Parameters { get; set; } but to no avail - the generic function still uses the base class' Parameters property. The only way to get a handle on the overridden property is to explicitly cast command (in the Prepare function) to my custom type, which is obviously what I don't want to do.
Am I missing something here?
First, new doesn't override the parameter, it's hiding it. This means that anyone using DbCommand.Parameters will see the original implementation while anyone using your type will see your implementation.
Overriding a property can only be done using the override keyword. In this case, you can't override Parameters because it isn't virtual.
Second, DbCommand.Parameters is just an external interface over the protected abstract DbCommand.DbCommandParameterCollection property. You need to implement this method to return a actual parameter collection.
OK, I managed to sort out the issue. Can't believe I've been blind to this the whole morning! When implementing a new class that inherits from System.Data.Common.DbCommand you have to override the DbParameterCollection property, among others. In my haste to create the new class I just returned null in the getter of this property and, I assume, that's what the Parameters property uses.
So I just implemented a new class that inherits from System.Data.Common.DbParameterCollection and returned a new instance of that class in my getter and it's working now!

Extension Methods and generics - How should I be doing this?

I'm in the middle of overhauling some code and I hit a bit of a snag.
This is the method which I currently have, it needs reworking to support some structure changes:
/// <summary>
/// Recreates a dashboard control based off of its settings.
/// </summary>
/// <typeparam name="T"> The type of control to be recreated. </typeparam>
/// <param name="settings"> The known settings needed to recreate the control.</param>
/// <returns> The recreated control. </returns>
public static T Recreate<T>(ISetting<T> settings) where T : new()
{
T _control = new T();
settings.SetSettings(_control);
Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
return _control;
}
ISetting is being removed completely in favor of an extension method known to _control.
So, I have now:
public static class RadControlExtensions
{
public static RadDockZoneSetting GetSettings(this RadDockZone dockZone)
{
RadDockZoneSetting radDockZoneSetting = new RadDockZoneSetting(dockZone.UniqueName, dockZone.ID, dockZone.Skin, dockZone.MinHeight,
dockZone.HighlightedCssClass, dockZone.BorderWidth, dockZone.Parent.ID);
return radDockZoneSetting;
}
public static RadTabSetting GetSettings(this RadTab tab, int index)
{
RadTabSetting radTabSetting = new RadTabSetting(tab.Text, tab.Value, index);
return radTabSetting;
}
//Continued
}
The control that is being recreated is guaranteed to have this extension method (would be nice to enforce this, though.)
I'm now at:
public static T Recreate<T>() where T : new()
{
T _control = new T();
//Not right -- you can't cast a control to an extension method, obviously, but
//this captures the essence of what I would like to accomplish.
(_control as RadControlExtension).SetSettings();
Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
return _control;
}
What should I be looking into to support this, if possible?
If you know that every _control that gets passed will be a RadDockZone (or derived from RadDockZone) just do this:
T _control = new T();
(RadDockZone)_control.SetSettings();
Logger.DebugFormat("Recreated control ... //rest of code here
If it's not always going to be a RadDockZone, you'll need to do some type checking to get the right type to call the extension method. I'm presuming, there, that you have a .SetSettings() extension method on all the possible Types that could be passed to your Recreate method.
You need to cast your T to something that is supported by your extension method.
(_control as RadDockZone).GetSettings
Extension methods operate on a type they are not a type in the traditional sense. The 'SomeFn(string this)' makes your extension work on things that are strings which would be strings and anything derived from them.
If I understand correctly what you are trying to do, just put a constraint on T:
public static T Recreate<T>() where T : RadControl, new() {
// etc.
}
You might have to use double dispatch and define
public static RadControl GetSettings(this RadControl control) {
}
which will invoke the appropriate GetSettings method.
No, Jason's answer is the cleaner way to go. The accepted solution killed the type safety and made use of generics pointless. You could switch to generic-less design (having a RadControlFactory) and had the job done.

protobuf-net inheritance

Marc mentioned on stackoverflow that it will be possible in v2 of protobuf-net to use ProtoInclude attribute (or similar approach) to serialize/deserialize class hierarchy without a need to specify each subtype in the base class. Is this implemented yet? We have a plugin interface that can be derived in external libraries, so there is no way of knowing what the derived types will be. We could maintain unique numbering between types though, but I couldn’t find any examples on the net, short of using ProtoInclude attribute which requires a subtype to be specified.
How would I go about implementing inheritance with protobuf-net like that if I don't know what the subtypes are?
If you can't specify the subtypes in attributes (because it isn't known at compile-time) you have 2 options (both of which only apply to "v2", available as beta):
use a RuntimeTypeModel, rather than the static Serializer methods (which are now just a short-cut to RuntimeTypeModel.Default); tell the model about the inheritance (example below)
add DynamicType = true to the [ProtoMember(...)] in question
The second is not very pure protobuf - it embeds type information, which I don't really love but people just kept asking for. The first is my preferred option. To add subtypes at runtime:
var model = TypeModel.Create();
var type = model.Add(typeof(YourBaseType), true);
var subTypeA = model.Add(typeof(SomeSubType), true);
var subTypeB = model.Add(typeof(SomeOtherSubType), true);
type.AddSubType(4, typeof(SomeSubType));
type.AddSubType(5, typeof(SomeOtherSubType));
the true in the above means "use normal rules to add member properties automatically" - you can also take control of that and specify the properties (etc) manually if you prefer.
Note that a TypeModel should be cached and re-used (not created per object you need to serialize), as it includes some "emit" code to generate methods. Re-using it will be faster and require less memory. The type-model is thread-safe, and can be used to serialize/deserialize multiple streams concurrently on different threads.
To further expand Marc's answer, specifically dealing with RuntimeTypeModel, this is one way to write it:
RuntimeTypeModel.Default[typeof(BaseClass)].AddSubType(20, typeof(DerivedClass));
If you have more classes derived from derived classes, link them like this
RuntimeTypeModel.Default[typeof(DerivedClass)].AddSubType(20, typeof(DerivedFromDerivedClass ));
And so on.
You can then use Serializer.Serialize(file,object), as you would normally with protobuf-net.
This works across projects and namespaces.
By adding helper extension method:
public static class RuntimeTypeModelExt
{
public static MetaType Add<T>(this RuntimeTypeModel model)
{
var publicFields = typeof(T).GetFields().Select(x => x.Name).ToArray();
return model.Add(typeof(T), false).Add(publicFields);
}
}
You can streamline sub-type registration like this:
private static RuntimeTypeModel CreateModel()
{
var model = TypeModel.Create();
model.Add<ExportInfo>();
model.Add<RegistrationInfo>();
model.Add<FactorySetupInfo>()
.AddSubType(101, model.Add<ServiceSetupInfo>().Type)
.AddSubType(102, model.Add<GenericWrapperSetupInfo>().Type)
.AddSubType(103, model.Add<DecoratorSetupInfo>().Type);
return model;
}
I solved this by completely flattening the hierarchy of fields for each ProtoContract. I also assume all fields will be serialized unless [ProtoIgnore] exists and therefore do not decorate fields with [ProtoMember(n)]. It does not need oneOf or [ProtoInclude]. This is what I use, no more scratching my head wondering what went wrong in the numbering etc. Feel free to expand on it to your needs.
A note: it takes any Type decorated with ProtoContract in an Assembly, flattens it's fields, ignores those with [ProtoIgnore], then automatically builds up all the ProtoMembers(n) (so no need for manual numbering).
It also accepts a single Generic Argument Protocol, where you supply the known Generic types e.g MyContract'1 and you supply typeof(MyContract2) such that the concreted type for serializing is MyContract<MyContract2>
Edit: This is a basic example and serves my needs. You may wish to extend it and sort the fields like so, so that you can manage adding new fields and retain backwards compat.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-member-order
To this end you could ignore Proto attributes entirely in the code and replace with DataContract, DataMember etc for discovery and let your contracts be both DataContracts and ProtoContracts with known ordering for both.
/// <summary>
/// <see cref="CompileProtocols(Assembly, Type[])"/>.
/// </summary>
/// <param name="knownGenericArguments"></param>
/// <returns></returns>
public static IEnumerable<Type> CompileProtocols(params Type[] knownGenericArguments)
{
var rv = CompileProtocols(Assembly.GetExecutingAssembly(), knownGenericArguments);
return rv;
}
/// <summary>
/// Compiles protocols that are non generic or take a single generic argument (`1). Single generic argument protocols
/// will be concreted against the knownGenericArguments passed into the method.
/// </summary>
/// <param name="genericArgumentTypes"></param>
public static IEnumerable<Type> CompileProtocols(Assembly inAssembly, params Type[] knownGenericArguments)
{
var runtimeProtocolTypes = new List<Type>();
var assemblyProtocolTypes =inAssembly.GetTypes().Where(t => t.GetCustomAttribute<ProtoContractAttribute>() != null);
foreach(var assemblyProtocolType in assemblyProtocolTypes)
{
if(assemblyProtocolType.IsGenericType == false)
{
runtimeProtocolTypes.Add(assemblyProtocolType);
}
else
{
if (knownGenericArguments.Length > 0)
{
var assemblyTypeGenericArgs = assemblyProtocolType.GetGenericArguments();
if (assemblyTypeGenericArgs.Length == 1)
{
foreach (var knownGenericArgument in knownGenericArguments)
{
var runtimeGenericType = assemblyProtocolType.MakeGenericType(knownGenericArgument);
runtimeProtocolTypes.Add(runtimeGenericType);
}
}
}
}
}
BuildModel(runtimeProtocolTypes);
return runtimeProtocolTypes;
}
/// <summary>
/// Builds and optionally compiles (default=true) the RuntimeTypeModel. In this case it uses the RumtimeTypeModel.Default
/// with a CompileInPlace.
///
/// Note: You might wish to change this to build another model or return a complete Compiled model instead.
/// </summary>
/// <param name="protocolTypes"></param>
/// <param name="compile"></param>
private static void BuildModel(IEnumerable<Type> protocolTypes, bool compile = true)
{
foreach (var protocolType in protocolTypes)
{
int index = 1;
var fields = protocolType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Where(f => f.GetCustomAttribute<ProtoIgnoreAttribute>() == null);
var metaType = RuntimeTypeModel.Default.Add(protocolType);
foreach (var field in fields)
{
metaType.AddField(index, field.Name);
index++;
}
}
if (compile)
{
RuntimeTypeModel.Default.CompileInPlace();
}
}

Categories