I have this class
public class MyViewModel<T> where T : class
{
public MyViewModel(
Func<IEnumerable<T>, MyService<T>> myServiceFactory,
IEnumerable<T> list)
{
}
}
and I need to register the Func in the bootstrapper.
I tried something like
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
but I can't get it working. Can anyone help me?
As you already noticed, what you're trying to do does not compile. Without defining the T somewhere, the C# compiler doesn't understand. Without a staticly defined T, you would have to define the types using reflection, but you'll hit limits of Autofac and C# pretty soon. You're code becomes very nasty. Instead, you'll have to extract this code in a helper method:
private static void RegisterMyServiceFactory<T>(IContainerBuilder builder) {
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
With this method need to call this method for every T you need in your application:
RegisterMyServiceFactory<Customer>(builder);
RegisterMyServiceFactory<Order>(builder);
RegisterMyServiceFactory<Employee>(builder);
This solution isn't particularly nice, but this is because you're missing an abstraction. Instead of letting your consumers depend upon Func<IEnumerable<T>, MyService<T>>, you should create a specific abstraction for consumers to depend upon:
public interface IServiceFactory<T> {
MyService<T> Resolve(IEnumerable<T> collection);
}
And embed your code in an IServiceFactory<T> implementation:
private sealed class AutofacServiceFactory<T> : IServiceFactory<T> {
private readonly IComponentContext context;
public AutofacServiceFactory(IComponentContext context) {
this.context = context;
}
public MyService<T> Resolve(IEnumerable<T> collection) {
return context.Resolve<MyService<T>>(collection);
}
}
You can register this open generic type as follows:
builder.RegisterGeneric(typeof(AutofacServiceFactory<>))
.As(typeof(IServiceFactory<>));
If the builder.Register code is executed by an instance of a MyViewModel it could/should work.
Otherwise it depends on how/if the T is declared in your particular context and you'll need to supply more info.
Anyway, your problem does not seem to be related to autofac in anyway. It's related to the use of generics. The Register method is indeed a generic method, but the generic parameter has to be ultimately translated to a concrete type when the call is made. So, unless T is properly declared in the context of the call to builder.Register then it won't work as it seems you are trying to register a whole range of types.
Related
I want to use Autofac to create a new instance of one or several WCF channels for a given unit of work. I'd like to use the command pattern to represent units of work, i.e. a given command class is injected with the channel(s) it needs and implements a bunch of related operations.
I tried the following:
interface IUnitOfWork
{
}
class FooCall : IUnitOfWork
{
readonly BarChannel _channel;
public FooCall(BarChannel channel)
{
Console.WriteLine($"FooCall({new {channel}})");
_channel = channel;
}
public string Foo()
{
return "FOO";
}
}
class BarChannel
{
public BarChannel()
{
Console.WriteLine("BarChannel()");
}
}
class FooService
{
Func<Owned<FooCall>> _helperFn;
public FooService(Func<Owned<FooCall>> helperFn)
{
_helperFn = helperFn;
}
public void CallFoo()
{
using (var helper = _helperFn())
{
Console.WriteLine($"CallFoo(), helper={helper}");
helper.Value.Foo();
}
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BarChannel>().InstancePerOwned<IUnitOfWork>();
builder.RegisterType<FooCall>().AsImplementedInterfaces().AsSelf();
builder.RegisterType<FooService>();
using (var scope = builder.Build().BeginLifetimeScope())
{
Console.WriteLine("call 1");
scope.Resolve<FooService>().CallFoo();
Console.WriteLine("call 2");
scope.Resolve<FooService>().CallFoo();
}
}
}
In short: a service method creates an owned unit of work; the unit of work is injected with a per-owned channel that it calls. The code sample should show two channel instances being created.
Except that it seems that the lifetime scope created for owned dependencies is only tagged with the type as which the dependency was resolved - i.e. as FooCall, not as IUnitOfWork. If I register BarChannel as InstancePerOwned<FooCall>, the code works; as is, registered as InstancePerOwned<IUnitOfWork>, it fails to resolve FooService since it can't find a matching lifetime scope. Am I missing something or is what I want to do not possible with Autofac? I'd rather not have to register all my WCF channels as instance-per-owned for every command class, that seems like it would get pretty verbose. Another workaround would be using instance-per-depedency and resolving a Func directly, but that won't let me say compose units of work while reusing channels and their dependencies between them.
The problem is that InstancePerOwned<T> is really just a special case of InstancePerMatchingLifetimeScope(params object[] lifetimeScopeTag), where the scope is tagged with something like typeof(T). As it stands, there needs to be a direct link between the tag provided there and the one attached to the scope when attempting to resolve, which is always set to the type of whatever's inside that specific Owned<> dependency. There's no additional logic to imply relations between types at that point, it's just a direct match on the tags.
However, InstancePerMatchingLifetimeScope does allow multiple tags to be specified, so it's possible to do something like:
builder.RegisterType<BarChannel>()
.InstancePerMatchingLifetimeScope(new TypedService(typeof(FooCall)),new TypedService(typeof(AnotherUnitOfWork)));
To wrap this up a bit more neatly you could use:
private static IEnumerable<Type> GetTypesImplementingInterface<TInterface>()
{
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(TInterface).IsAssignableFrom(p));
}
and then a new extension method:
public static class AutofacRegistrationBuilderExtensions
{
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerOwned<TLimit, TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, IEnumerable<Type> serviceTypes)
{
return builder.InstancePerMatchingLifetimeScope(serviceTypes.Select(s => new TypedService(s)).ToArray());
}
}
The usage would then just be:
builder.RegisterType<BarChannel>().InstancePerOwned(GetTypesImplementingInterface<IUnitOfWork>());
I'm not sure if the last part there would be worth pulling into Autofac itself, but I guess if it did then it might be better to combine the two methods above together and retrieve the list of types applicable from existing registrations, e.g. something like
InstancePerOwnedImplementing<TInterface>();
Alternatively, it would probably be a bit messy to extend the matching scope logic to check the relationship between types at resolution time, since not all tags are of the type Type.
I am trying to register a Func<string> with TinyIoc.:
container.Register<Func<string>>(() => myObject.MyProperty);
and a type that depends on it with a constructor:
MyDependentType(Func<string> function)
when I use
container.Resolve<MyDependentType>()
it's all fine, but i cannot register a second Func<string> because it can not be resolved. It's ambigious I guess.
No Error is thrown, but the injected Func is the wrong one.
I tried to add names, no success.
Does TinyIoc actually support that?
Or do I have to wrap my functions into objects? Like strategy pattern?
You are right, it is ambiguous to map the same type more than once. No DI container can handle this, because there is no way to tell one Func<string> from another Func<string>.
That said, your usage example seems really unusual. Normally, if you want a property inside of another object, you inject the object that property belongs to, not a Func<string>.
class MyObject : IMyObject
{
public string MyProperty { get { return "foo"; } }
}
class MyDependentType : IMyDependentType
{
private readonly IMyObject myObject;
public MyDependentType(IMyObject myObject)
{
this.myObject = myObject;
}
public void DoSomething()
{
var myProperty = this.myObject.MyProperty;
// do something with myProperty...
}
}
Like NightOwl888 said, those Func<> objects are ambiguous.
In the end I used a factory lambda.
container.Register<IMyType>((c, o) => {
var dep = c.Resolve<IDependentType>();
return new MyConcreteClass(() => dep.DependantFunc);
});
It's a bit much, but now I can let TinyIoc resolve my dependencies.
I just have to create the factory lambda.
I am trying to implement a complex builder to help my testing context. To do that I refactored my code to have a method :
public TestContext Add<T>(Action<IBuilder<T>> configurator) where T : class, new()
{
IBuilder<T> builder = CreateBuilderOf<T>();
configurator(builder);
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
The problem arises when I need to specify the configuration when calling the method :
TestContext.Instance.Add<Person>(personBuilder => ((PersonBuilder)personBuilder).Name("SMITH"));
I need to be able to use type specific methods in the configurator, which are implemented by the concrete builders, such as :
public PersonBuilder : IBuilder<Person>
{
private Person Item;
public PersonBuilder() { Item = new Person(); }
public Name(string mame) { Item.Name = name; }
public Person GetItem() { return Item; }
}
Apparently, passing an Action<PersonBuilder> as an Action<IBuilder<Person>> is not allowed, even though PersonBuilder implements IBuilder<Person>, hence the cast.
I would very much like to either :
Need not to cast inside the lambda but rather at the start of it, e.g.
(PersonBuilder personBuilder) => personBuilder.Name("SMITH"), but that boils down to being an instance of Action<PersonBuilder> and therefore is equally invalid;
Use a function such as BuildSimplePerson(PersonBuilder builder) in Add's argument : Add<Person>(BuildSimplePerson)
I think I can do a type casting through two BuildSimplePersons implementations such as :
private void BuildSimplePerson(IBuilder<Person> builder)
{
BuildSimplePerson(builder as PersonBuilder);
}
private void BuildSimplePerson(PersonBuilder builder)
{
builder.Name("SMITH");
}
But that is not really an elegant solution.
I also realize passing Action<PersonBuilder> as an Action<IBuilder<Person>> is incorrect because we don't know if the argument to that function will truly be a PersonBuilder or any other implementation of IBuilder<Person>.
How can I do better ?
As my comment already states, the problem is that your current code assumes that CreateBuilderOf<T> returns a PersonBuilder but it could actually return anything that implements IBuilder<Person> in which case your cast would fail.
Your code looks like it is generic, but in fact, it is not. You always want to work on the concrete class (PersonBuilder) and not on the general interface IBuilder<Person>.
My understanding is, that you want one generic Add<T> method to avoid having to repeat that code inside it for each type.
Here is my approach:
public TestContext Add<T>(IBuilder<T> builder) where T : class, new()
{
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
You would call it like this:
TestContext.Instance.Add<Person>(CreatePersonBuilder().Name("SMITH"));
Obviously, you would need to have a CreateXBuilder method for each type that you want to be able to add. However, I think you already have this at least implicitly, because I would assume that your CreateBuilderOf<T> method is one huge switch statement anyway.
If you don't want to create such methods, another approach to get the builder would be a generic method like so:
CreateBuilder<PersonBuilder>()
But really, this is actually nothing more than a new PersonBuilder(), so you actually could simply go with
TestContext.Instance.Add<Person>(new PersonBuilder().Name("SMITH"));
The Configure method would be very similar:
TestContext.Instance.Configure<Person>(id, p => new PersonBuilder(p).Name("SMITH"));
This would pass the ID, which the Configure method would use to look up the object, which in turn is passed to the callback. So the second parameter of Configure would not be a Action<IBuilder<T>> but an Action<T>.
This approach has another advantage over your existing code:
Your existing code assumes not just that PersonBuilder will be the implementation used for IBuilder<Person>. No, your code also assumes that it has a constructor without parameters and one which takes a Person. These assumptions are impossible for the compiler to verify.
With the code I showed above, a builder implementation could take additional parameters without problems and the compiler would verify that everything is alright.
What would be the most efficient way to instanciate an object according to a generic type passed to a Factory class, for instance:
public class LoggerFactory
{
public static ILogger<T> Create<T>()
{
// Switch Statement?
// Generic Dictionary?
// EX.: if "T" is of type "string": return (ILogger<T>)new StringLogger();
}
}
How would you do it? Which branching statement? etc...
I think it's best to keep it simple, perhaps something like this:
public static class LoggerFactory
{
static readonly Dictionary<Type, Type> loggers = new Dictionary<Type, Type>();
public static void AddLoggerProvider<T, TLogger>() where TLogger : ILogger<T>, new()
{
loggers.Add(typeof(T), typeof(TLogger));
}
public static ILogger<T> CreateLogger<T>()
{
//implement some error checking here
Type tLogger = loggers[typeof(T)];
ILogger<T> logger = (ILogger<T>) Activator.CreateInstance(tLogger);
return logger;
}
}
You just call the AddLoggerProvider for each type you want to support, can be extended at runtime, it ensures you definetly add an implementation of the interface to the library and not some object, isn't very fast because of the Activator, but creating a logger wont likely be a bottleneck anyway. Hope it looks okay.
Usage:
// initialize somewhere
LoggerFactory.AddLoggerProvider<String, StringLogger>();
LoggerFactory.AddLoggerProvider<Exception, ExceptionLogger>();
// etc..
ILogger<string> stringLogger = LoggerFactory.CreateLogger<string>();
Note: each ILogger<T> requires a parameterless constructor for the Activator, but that too is ensured with the new() generic constraint in the add method.
I think I'd do it like this:
public class LoggerFactory<T>
{
private static Dictionary<Type, Func<ILogger<T>>> LoggerMap =
new Dictionary<Type, Func<ILogger<T>>>
{
{ typeof(string),
() => new StringILogger() as ILogger<T> },
{ typeof(StringWriter),
() => new StringWriterILogger() as ILogger<T> }
};
public static ILogger<T> CreateLogger()
{
return LoggerMap[typeof(T)]();
}
}
You pay something of a readability price (all those angle brackets, sheesh), but as you can see it makes for very little program logic.
Although I typically would recommend using a dependency injection framework, you could implement something with reflection that would search the available types for one that implements the appropriate ILogger interface.
I would suggest that you carefully consider which assemblies will contain these logger implementations and how extensible and bullet-proof you want the solution to be. Performing runtime searches across the available assemblies and types is not inexpensive. It is, however, an easy way to allow extensibility in this type of design. It also avoid the issue of up-front configuration - however it requires that only a single concrete type implement a particular version of the ILogger<> interface - otherwise there's an ambiguous situation you have to resolve.
You may want to perform some internal caching to avoid the expense of performing reflection on each call to Create().
Here is some sample code you could start with.
using System;
using System.Linq;
using System.Reflection;
public interface ILogger<T> { /*... */}
public class IntLogger : ILogger<int> { }
public class StringLogger : ILogger<string> { }
public class DateTimeLogger : ILogger<DateTime> { }
public class LoggerFactory
{
public static ILogger<T> Create<T>()
{
// look within the current assembly for matching implementation
// this could be extended to search across all loaded assemblies
// relatively easily - at the expense of performance
// also, you probably want to cache these results...
var loggerType = Assembly.GetExecutingAssembly()
.GetTypes()
// find implementations of ILogger<T> that match on T
.Where(t => typeof(ILogger<T>).IsAssignableFrom(t))
// throw an exception if more than one handler found,
// could be revised to be more friendly, or make a choice
// amongst multiple available options...
.Single();
/* if you don't have LINQ, and need C# 2.0 compatibility, you can use this:
Type loggerType;
Type[] allTypes = Assembly.GetExecutingAssembly().GetTypes();
foreach( var type in allTypes )
{
if( typeof(ILogger<T>).IsAssignableFrom(type) && loggerType == null )
loggerType = type;
else
throw new ApplicationException( "Multiple types handle ILogger<" + typeof(T).Name + ">" );
}
*/
MethodInfo ctor = loggerType.GetConstructor( Type.EmptyTypes );
if (ctor != null)
return ctor.Invoke( null ) as ILogger<T>;
// couldn't find an implementation
throw new ArgumentException(
"No mplementation of ILogger<{0}>" + typeof( T ) );
}
}
// some very basic tests to validate the approach...
public static class TypeDispatch
{
public static void Main( string[] args )
{
var intLogger = LoggerFactory.Create<int>();
var stringLogger = LoggerFactory.Create<string>();
var dateTimeLogger = LoggerFactory.Create<DateTime>();
// no logger for this type; throws exception...
var notFoundLogger = LoggerFactory.Create<double>();
}
}
Depends on how many types you intend to handle. If it's small (less than 10) I'd suggest a switch statement, as it'll be fast and cleaner to read. If you want more you would want a lookup table (Hash Map, Dictionary, etc), or some reflection based system.
switch statement vs dictionary - doesn't matter for perfomance, as a switch is compiled into a dictionary. So really it's a matter of readabilty and flexibility. The switch is easier to read, on the other hand a dictionary can be extended at runtime.
You might consider using a dependency injection framework here like Unity. You can configure it with the generic types that your factor will return and do the mapping in configuration. Here's an example of that.
1) I'm always amazed at the complexity people put into logging. Always seems like overkill to me. If log4net is opensource, I'd recommend you go look at that, infact, you might just as well use it ...
2) Personally, I try to avoid type checking whenever possible - it defeats the point of generics. Just use the .ToString() method and be done with it.
Hrm... you could actually try to be a little more clever about this, depending on what the given runtime system supported. I actually try to avoid any conditional statements in my code if I can, especially in polymorphic and dynamically bound code. You've got a generic class there, so why not use it?
For example, in Java, you can especially make use of the static method you've got there to do something like this:
public class LoggerFactory<T>
{
public static ILogger<T> CreateLogger(Class<? extends SomeUsefulClass> aClass);
{
// where getLogger() is a class method SomeUsefulClass and its subclasses
// and has a return value of Logger<aClass>.
return aClass.getLogger();
// Or perhaps you meant something like the below, which is also valid.
// it passes the generic type to the specific class' getLogger() method
// for correct instantiation. However, be careful; you don't want to get
// in the habit of using generics as variables. There's a reason they're
// two different things.
// return aClass.getLogger(T);
}
}
You'd call it like this:
public static void main(String[] args)
{
Logger = LoggerFactory.createLogger(subclassOfUsefulClass.class);
// And off you go!
}
This avoids having to have any conditionals and is more flexible besides: any class that's a subclass (or implements the logger interface, perhaps) of SomeUsefulClass can return the correctly typed logger instance.
I'm writing some tests, and frequently I find myself having to look up generic parameters to pass explicitly pass along.
public class MyService : SecureService<RootEntity>
{
//Intentionally omitted does not provide information related to question
}
public DepedencyReplaceScope<IContextProvider> CreateMockScope<TRootEntity>
{
var mockCtx = Mock.Of<IContextProvider>(x => x.WriteContext<TRootEntity> == new FakeContext<TRootEntity>())
return new DependencyReplaceScope(mockCtx);
}
Currently when I'm creating mocks for my test, I have too go into the service and find out what it's root is to pass along. However, It would be a lot nicer if I could create a scope based on the service.
e.g (pseudo code)
public DepedencyReplaceScope<IContextProvider> CreateMockScopeFromService<TService>
where TService : SecureService<>
define TRootEntity : TService<()>
{
return CreateMockScope<TRootEntity>();
}
This won't work since I don't think there is a way to define a proxy for the Generic. Is there a way to create this scope solely from the TService (I don't want to use reflection directly to build it, but I don't mind using a hack with a moq since it abstracts the reflection)
The best thing I was able to come up so far was:
public static class MockScopeProvider
{
public static DepedencyReplaceScope<IContextProvider> CreateMockScopeFromService<U>(SecureService<U> dummy)
{
// your logic....
var mockCtx = Mock.Of<IContextProvider>(x => x.WriteContext<U>() == new FakeContext<U>());
return new DependencyReplaceScope(mockCtx);
}
}
With usage being like that:
MockScopeProvider.CreateMockScopeFromService(default(MyService));