Decorating a generic interface with Structuremap - c#

I have a generic interface, that takes in two generic types. I want to decorate all versions returned, but since I don't know the type when calling EnrichWith, it obviously doesn't compile. I've tried using the EnrichWith overload that passes in the context, thinking maybe I could grab the generic types passed in and call Activator.CreateInstance, but the context doesn't have any useful information on it when debugging and inspecting it.
Here's what I have so far. This is my generic interface:
public interface IServiceOperation<in TRequest, out TResponse> where TResponse : ServiceResult, new()
{
TResponse PerformService(TRequest validatedRequest);
}
Here's a sample implementation:
public class SignUpService : IServiceOperation<SignUpRequest, SignUpResult>
{
private readonly IUserRepository _userRepo;
public SignUpService(IUserRepository userRepo)
{
_userRepo = userRepo;
}
public SignUpResult PerformService(SignUpRequest validatedRequest)
{
var user = Mapper.Map<User>(validatedRequest);
user.MarkAsLoggedIn();
user.ChangePassword(validatedRequest.UnhashedPassword);
using(var transaction = _userRepo.BeginTransaction())
{
_userRepo.Save(user);
transaction.Commit();
}
return new SignUpResult();
}
}
Here is my decorator, that takes in another service as well:
public class ValidateServiceDecorator<TRequest, TResponse> : IServiceOperation<TRequest, TResponse> where TResponse : ServiceResult, new()
{
private readonly IServiceOperation<TRequest, TResponse> _serviceOperation;
private readonly IValidationService _validationService;
public ValidateServiceDecorator(IServiceOperation<TRequest, TResponse> serviceOperation,
IValidationService validationService)
{
_serviceOperation = serviceOperation;
_validationService = validationService;
}
public TResponse PerformService(TRequest request)
{
var response = new TResponse();
var validationResult = _validationService.Validate(request);
if (!validationResult.IsValid)
{
response.ValidationErrors = validationResult.ValidationErrors;
return response;
}
return _serviceOperation.PerformService(request);
}
Lastly, here is how far I've gotten on my container. This obviously doesn't compile, but the EnrichWith line shows what I'm trying to achieve:
public class StructureMapServiceScanner : Registry
{
public StructureMapServiceScanner()
{
Scan(scanner =>
{
scanner.AssemblyContainingType(typeof (IServiceOperation<,>));
scanner.ConnectImplementationsToTypesClosing(typeof (IServiceOperation<,>));
});
For(typeof (IServiceOperation<,>))
.EnrichWith((ioc, original) => new ValidateServiceDecorator(original, ioc.GetInstance<IValidationService>()));
}
}
And just because this question needed a little more code, here's my test that I'm trying to get to pass:
[TestClass]
public class StructureMapServiceScannerSpecs
{
[TestMethod]
public void Test()
{
ObjectFactory.Configure(cfg =>
{
cfg.AddRegistry<StructureMapServiceScanner>();
cfg.For<IUserRepository>().Use(new Mock<IUserRepository>().Object);
cfg.For<IValidationService>().Use(new Mock<IValidationService>().Object);
});
var service = ObjectFactory.GetInstance<IServiceOperation<SignUpRequest, SignUpResult>>();
service.ShouldNotBeNull();
service.ShouldBeType<ValidateServiceDecorator<SignUpRequest, SignUpResult>>();
}
}
I feel like this is something that should be simple, and I'm really missing something with how to use StructureMap. I could create type-specific versions for all combinations of Request and Response types, but obviously that's not desirable. So what am I missing?

Was able to figure it out, eventually. I created a RegistrationConvention:
public class ServiceRegistrationConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
var interfacesImplemented = type.GetInterfaces();
foreach (var interfaceImplemented in interfacesImplemented)
{
if (interfaceImplemented.IsGenericType && interfaceImplemented.GetGenericTypeDefinition() == typeof(IServiceOperation<,>))
{
var genericParameters = interfaceImplemented.GetGenericArguments();
var closedValidatorType = typeof(ValidateServiceDecorator<,>).MakeGenericType(genericParameters);
registry.For(interfaceImplemented)
.EnrichWith((context, original) => Activator.CreateInstance(closedValidatorType, original,
context.GetInstance<IValidationService>()));
}
}
}
}

Here's an approach that still leverages StructureMap's IoC capabilities, allowing additional services to be injected easily into your decorator. It's not perfect since it assumes you are using the primary container and not a child container, but it will probably work for most scenarios.
public class ServiceRegistrationConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
var handlerInterfaces = (from t in type.GetInterfaces()
where t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof (IHandle<,>)
select t);
foreach (var handler in handlerInterfaces)
{
var decoratorType = typeof (ValidationDecorator<,>).MakeGenericType(handler.GetGenericArguments());
registry.For(handler)
.EnrichWith((ctx, orig) => ObjectFactory.With(handler, orig).GetInstance(decoratorType));
}
}
}
Ideally, StructureMap's IContext should expose the With method just like IContainer does. Without that, there's not really a great solution to this problem.

Related

Do I need dependency injection to automatically register my message handlers?

I have RegisterMessageHandlers that register message handler per message name.
I want to automatically find and register all handlers through reflection. I can annotate each message with MessageAttribute (like shown below) and get the message name through reflection as well. The problem is when I want to instantiate a handler via Activator I have to provide all the dependencies in the constructor.
My solution is to register all instances with DI and pass IServiceProvider to MainManagerClass(IServiceProvider provider) and then use ActivatorUtilities.CreateInstance(handlerType) to instantiate each discovered handler through reflection.
But, then I read that there is DI and service locator which is antipattern and it's not very clear when one becomes the other.
So, I think I need a DI in order to accomplish what I want. Or do I?
public class MainManagerClass
{
private Dictionary<string, MessageHandler> _handlers;
private void RegisterMessageHandlers()
{
_messageHandlers["msg1"] = new MessageHandler1(new Service1());
_messageHandlers["msg2"] = new MessageHandler2(new Service1(), new Service2());
}
}
public class MessageHandler1 : MessageHandler<Message1>
{
public MessageHandler1(IService1 service){}
}
public class MessageHandler2 : MessageHandler<Message2>
{
public MessageHandler1(IService1 service1, IService2 service2){}
}
public abstract class MessageHandler<T> : MessageHandler
{
}
public abstract class MessageHandler
{
}
[Message("msg1")]
public class Message1
{
}
UPDATE
public class MainManagerClass
{
private Dictionary<string, MessageHandler> _handlers;
private readonly IServiceProvider _serviceProvider;
public MainManagerClass(IServiceProvider serviceProvider)
{
}
private void RegisterMessageHandlers()
{
var messageHandlers = Assembly.GetCallingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(MessageHandler))).ToList();
foreach (var handler in messageHandlers)
{
var messageType = handler.BaseType.GenericTypeArguments[0];
var msgAttribute = messageType.CustomAttributes
.Where(t => t.AttributeType == typeof(MessageAttribute))
.FirstOrDefault();
if (msgAttribute == null)
throw new Exception($"Message name not defined for message type {messageType.Name}");
var msgName = msgAttribute.ConstructorArguments[0].Value.ToString();
_messageHandlers[msgName] = ActivatorUtilities.CreateInstance(_serviceProvider, handler) as MessageHandler;
}
}
}
internal class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder().Build();
var manager = new MainManagerClass(host.Services);
...
}
private static IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder()
.ConfigureServices((_, services) =>
{
services
.AddSingleton<IService1, Service1>()
.AddSingleton<IService2, Service2>()
.AddSingleton<IService3, Service3>()
;
});
}
}
If you don't want to add interface and keep abstract class as in your example - you can register your handlers like that:
builder.Services.AddTransient<MessageHandler<Message1>, MessageHandler1>();
builder.Services.AddTransient<MessageHandler<Message2>, MessageHandler2>();
And then if you inject MessageHandler<Message1> in your controller for instance, MessageHandler1 will be resolved as well as other dependencies (IService1 in your case).
I think I still don't get your question but I hope this will be helpfull for you. Anyway, I followed Jaroslav's answer and your comment to create MessageHandlerFactory object then I changed your code a bit to cover both scenarios but you need the message type to resolve its handler from the service provider plus, If you want to register all handlers automatically, you should use reflection at startup, find all objects that inherit from IMessageHandler<T>, and register them to DI or use packages like Scrutor.
public class MessageHandlerFactory
{
private IServiceProvider _serviceProvider;
public IMessageHandler<T> ResolveHandler<T>()
{
return _serviceProvider.GetRequiredService<IMessageHandler<T>>();
}
}
public class MessageHandler1 : IMessageHandler<Message1>
{
public MessageHandler1(IService1 service){}
}
public class MessageHandler2 : IMessageHandler<Message2>
{
public MessageHandler2(IService1 service1, IService2 service2){}
}
public interface IMessageHandler<T>
{
}
public class Message1
{
}
public class Message2
{
}
builder.Services.AddScoped<IMessageHandler<Message1>, MessageHandler1>();
builder.Services.AddScoped<IMessageHandler<Message2>, MessageHandler2>();

DryIoc open generic interception with castle core

I want to register open generic interception, so I modified explample from https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/Interception.md
[TestFixture]
public class UnitTest3
{
public interface IFoo<T>
{
void Greet();
}
public class Foo<T> : IFoo<T>
{
public void Greet() { }
}
[Test]
public void Example()
{
var container = new Container();
container.Register(typeof(IFoo<>), typeof(Foo<>));
container.Register<FooLoggingInterceptor>(Reuse.Singleton);
container.Intercept<FooLoggingInterceptor>(typeof(IFoo<>));
var foo = container.Resolve<IFoo<int>>();
foo.Greet();
// examine that logging indeed was hooked up
var logger = container.Resolve<FooLoggingInterceptor>();
Assert.AreEqual("Invoking method: Greet", logger.LogLines[0]);
}
}
public class FooLoggingInterceptor : IInterceptor
{
public List<string> LogLines = new List<string>();
private void Log(string line) => LogLines.Add(line);
public void Intercept(IInvocation invocation)
{
Log($"Invoking method: {invocation.GetConcreteMethod().Name}");
invocation.Proceed();
}
}
public static class DryIocInterception
{
private static readonly DefaultProxyBuilder _proxyBuilder = new DefaultProxyBuilder();
public static void Intercept<TInterceptor>(this IRegistrator registrator, Type serviceType, object serviceKey = null)
where TInterceptor : class, IInterceptor
{
Type proxyType;
if (serviceType.IsInterface())
proxyType = _proxyBuilder.CreateInterfaceProxyTypeWithTargetInterface(
serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default); //Exception!!!
else if (serviceType.IsClass())
proxyType = _proxyBuilder.CreateClassProxyTypeWithTarget(
serviceType, ArrayTools.Empty<Type>(), ProxyGenerationOptions.Default);
else
throw new ArgumentException(
$"Intercepted service type {serviceType} is not a supported, cause it is nor a class nor an interface");
registrator.Register(serviceType, proxyType,
made: Made.Of(pt => pt.PublicConstructors().FindFirst(ctor => ctor.GetParameters().Length != 0),
Parameters.Of.Type<IInterceptor[]>(typeof(TInterceptor[]))),
setup: Setup.DecoratorOf(useDecorateeReuse: true, decorateeServiceKey: serviceKey));
}
}
But this throws exception:
Can not create proxy for type TestDryIoc.UnitTest3+IFoo`1 because type
TestDryIoc.UnitTest3+IFoo`1 is an open generic type.
Aparently Castle.Core doesn't support open generics. My other idea was to supply delegate, which will create the proxy class on resolve, when concrete generic param is known, but looks like DryIoc doesn't support open generic delegates...
Yeah, it is possible. So you need to find the closed type to pass it to the proxy? Wrap the code into the method and use the Made.Of which has access to the Request.ServiceType.

How to resolve type at run time to avoid multipe if else

I have my code which makes a webservice Call based on type of request.
To do that , I have following code;
public class Client
{
IRequest request;
public Client(string requestType)
{
request = new EnrolmentRequest();
if (requestType == "Enrol")
{
request.DoEnrolment();
}
else if (requestType == "ReEnrol")
{
request.DoReEnrolment();
}
else if (requestType == "DeleteEnrolment")
{
request.DeleteEnrolment();
}
else if (requestType == "UpdateEnrolment")
{
request.UpdateEnrolment();
}
}
}
So as per open close principle, I can subclass like:
Class EnrolmentRequest:IRequest
{
CallService();
}
Class ReEnrolmentRequest:IRequest
{
CallService();
}
Class UpdateEnrolmentRequest:IRequest
{
CallService();
}
Now my client class will look something like this:
public class Client
{
public Client(string requestType)
{
IRequest request;
if (requestType == "Enrol")
{
request = new EnrolmentRequest();
request.CallService();
}
else if (requestType == "ReEnrol")
{
request = new REnrolmentRequest();
request.CallService();
}
else if (requestType == "DeleteEnrolment")
{
request = new UpdateEnrolmentRequest();
request.CallService();
}
else if (requestType == "UpdateEnrolment")
{
request = new UpdateEnrolmentRequest();
request.CallService();
}
}
}
Now , I still have to use if and else , and will have to change my code if there are any new request type.
So, it's definitely, not closed to modification.
Am I missing any thing with respect to SOLID?
Can I use dependency injection, to resolve the types at Run time?
The need to write new code to handle new requirements is not going to disappear. The goal is to not have to change the old code when handling new requirements, and your class structure deals with it.
You can minimize the changes by replacing your chain of conditionals with some other mechanism of creating new instances. For example, you can build a dictionary, or use a dependency injection framework to associate a type with a string.
Here is an implementation without using DI framework:
private static readonly IDictionary<string,Func<IRequest>> ReqTypeMapper =
new Dictionary<string,Func<IRequest>> {
{"Enrol", () => new EnrolmentRequest() }
, {"ReEnrol", () => new ReEnrolmentRequest() }
, ...
};
Now the call will look like this:
Func<IRequest> maker;
if (!ReqTypeMapper.TryGetValue(requestType, out maker)) {
// Cannot find handler for type - exit
return;
}
maker().CallService();
You can't really remove the list of if-else or switch-case statements completely, unless you revert to using reflection. Somewhere in the system you will definately have some sort of dispatching (either using a hard-coded list or through reflection).
Your design however might benefit from a more message based approach, where the incomming requests are message, such as:
class DoEnrolment { /* request values */ }
class DoReenrolment { /* request values */ }
class DeleteEnrolment { /* request values */ }
class UpdateEnrolment { /* request values */ }
This allows you to create a single interface defenition for 'handlers' of such request:
interface IRequestHandler<TRequest> {
void Handle(TRequest request);
}
Your handlers will look as follows:
class DoEnrolmentHandler : IRequestHandler<DoEnrolment> {
public void Handle(DoEnrolment request) { ... }
}
class DoReenrolmentHandler : IRequestHandler<DoReenrolment> {
public void Handle(DoReenrolment request) { ... }
}
class DeleteEnrolmentHandler : IRequestHandler<DeleteEnrolment> {
public void Handle(DeleteEnrolment request) { ... }
}
Advantage of this is that applying cross-cutting concerns is a breeze, since it is very straightforward to define a generic decorator for IRequestHandler<T> that implements something like logging.
This still brings us back to the dispatching of course. Dispatching can be extracted from the client, behind its own abstraction:
interface IRequestDispatcher {
void Dispatch<TRequest>(TRequest request);
}
This allows the client to simply send the request it requires:
// Client
this.dispatcher.Dispatch(new DoEnrolment { EnrolId = id });
An implementation of the request dispatcher might look like this:
class ManualRequestDispatcher : IRequestDispatcher {
public void Dispatch<TRequest>(TRequest request) {
var handler = (IRequestHandler<TRequest>)CreateHandler(typeof(TRequest));
handler.Handle(request);
}
object CreateHandler(Type type) =>
type == typeof(DoEnrolment)? new DoEnrolmentHandler() :
type == typeof(DoReenrolment) ? new DoReenrolment() :
type == typeof(DeleteEnrolment) ? new DeleteEnrolment() :
type == typeof(UpdateEnrolment) ? new UpdateEnrolment() :
ThrowRequestUnknown(type);
object ThrowRequestUnknown(Type type) {
throw new InvalidOperationException("Unknown request " + type.Name);
}
}
If you use a DI Container however, you will be able to batch-register your request handlers with something as follows (depending on the library you use of course):
container.Register(typeof(IRequestHandler<>), assemblies);
And your dispatcher might look as follows:
class ContainerRequestDispatcher : IRequestDispatcher {
private readonly Container container;
public ContainerRequestDispatcher(Container container) {
this.container = container;
}
public void Dispatch<TRequest>(TRequest request) {
var handler = container.GetInstance<IRequestHandler<TRequest>>();
handler.Handle(request);
}
}
You can find more information about this type of design here and here.
You can add simple factory class like below:
public class ServiceFactory : Dictionary<string, Type>
{
public void Register(string typeName, Type serviceType) {
if (this.ContainsKey(typeName)) {
throw new Exception("Type registered");
}
this[typeName] = serviceType;
}
public IRequest Resolve(string typeName) {
if (!this.ContainsKey(typeName)) {
throw new Exception("Type not registered");
}
var type = this[typeName];
var service = Activator.CreateInstance(type);
return service as IRequest;
}
}
then register services in one place like:
var serviceFactory = new ServiceFactory();
serviceFactory.Register("Enrol", typeof(EnrolmentRequest));
serviceFactory.Register("ReEnrol", typeof(REnrolmentRequest));
serviceFactory.Register("DeleteEnrolment", typeof(UpdateEnrolmentRequest));
serviceFactory.Register("UpdateEnrolment", typeof(UpdateEnrolmentRequest));
and call it:
var service = serviceFactory.Resolve(requestType);
service.CallService();
also need to add proper error handling
Good question,
you can achieve your goal using one single method:
var request = (IRequest)Activator.CreateInstance("NameOfYourAssembly", requestType);
request.CallService();
Reflection will help you generating your class instance. After that you can call it without if/else.
Please refer to this link for more information about provided method: https://msdn.microsoft.com/it-it/library/3k6dfxfk(v=vs.110).aspx
Hope this can help
You can use Factory Pattern With RIP (Replace If with Polymorphism) to avoid multiple if-else.
Following code is the sample code according to your Client class :
public enum RequestType : int
{
Enrol = 1,
ReEnrol,
UpdateEnrolment
}
public interface IRequest
{
void CallService();
}
public class EnrolmentRequest : IRequest
{
public void CallService()
{
// Code for EnrolmentRequest
}
}
public class ReEnrolmentRequest : IRequest
{
public void CallService()
{
// Code for ReEnrolmentRequest
}
}
public class UpdateEnrolmentRequest : IRequest
{
public void CallService()
{
// Code for UpdateEnrolmentRequest
}
}
// Factory Class
public class FactoryChoice
{
private IDictionary<RequestType, IRequest> _choices;
public FactoryChoice()
{
_choices = new Dictionary<RequestType, IRequest>
{
{RequestType.Enrol, new EnrolmentRequest() },
{RequestType.ReEnrol, new ReEnrolmentRequest()},
{RequestType.UpdateEnrolment, new UpdateEnrolmentRequest()}
};
}
static public IRequest getChoiceObj(RequestType choice)
{
var factory = new FactoryChoice();
return factory._choices[choice];
}
}
and it will be call like :
IRequest objInvoice = FactoryChoice.getChoiceObj(RequestType.ReEnrol);
objInvoice.CallService();
Here, main things happened in the FactoryChoice class constructor. That's why someone called it smart constructor. This way you can avoid multilpe if-else or switch-case.
To know the basic of RIP you can check my slide here.
you can use autofac keyed or named service..
public enum OperationType
{
Enrol,
ReEnrol,
DeleteEnrolment,
UpdateEnrolment
}
//register types
builder.RegisterType<EnrolmentRequest>().Keyed<IRequest>(OperationType.Enrol);
builder.RegisterType<ReEnrolmentRequest>().Keyed<IRequest>(OperationType.ReEnrol);
builder.RegisterType<UpdateEnrolmentRequest>().Keyed<IRequest>(OperationType.DeleteEnrolment | OperationType.UpdateEnrolment);
// resolve by operationType enum
var request = container.ResolveKeyed<IRequest>(OperationType.Enrol);

Invoking a different constructor with autofixture [duplicate]

I'm using AutoFixture and I'd like to use a specific constructor.
I have the following code and I like to select the constructor with ITemplateParameterHandler.
public sealed class TemplateSegmentHandler : ITemplateSegmentHandler
{
public TemplateSegmentHandler(ITemplateIterator iterator)
: this(new TemplateParameterHandler(iterator))
{
Contract.Requires(iterator != null);
}
public TemplateSegmentHandler(ITemplateParameterHandler parameterHandler)
{
Contract.Requires(parameterHandler != null);
_parameterHandler = parameterHandler;
_parameterHandler.Ending += EndingParameter;
}
// ...
}
EDIT:
I want to inject the following fake implementation. (I'm using NSubstitute to create the fake object.)
public sealed class CustomTemplateParameter : ICustomization
{
private readonly ITemplateParameterHandler _context;
public CustomTemplateParameter()
{
_context = Substitute.For<ITemplateParameterHandler>();
}
public void Customize(IFixture fixture)
{
fixture.Customize<ITemplateParameterHandler>(c => c.FromFactory(() => _context));
}
public CustomTemplateParameter SetCatchAll(bool isCatchAll)
{
_context.IsCatchAll.Returns(isCatchAll);
return this;
}
}
Here is the way I'm trying to use it.
[Fact]
public void Should_return_true_when_the_segment_has_a_catch_all_parameter()
{
TemplateSegmentHandler segmentHandler = new Fixture().Customize(new TemplateSegmentHandlerFixture())
.Customize(new CustomTemplateParameterHandler()
.SetCatchAll(true))
.Create<TemplateSegmentHandler>();
segmentHandler.Parameter.Start();
segmentHandler.Parameter.End();
segmentHandler.HasCatchAll.Should().BeTrue();
}
But it still selects the wrong constructor and I'm getting the following error.
Ploeh.AutoFixture.ObjectCreationExceptionAutoFixture was unable to create an instance from Somia.Web.Routing.Template.ITemplateIterator, most likely because it has no public constructor, is an abstract or non-public type.
Request path:
Somia.Web.Routing.Template.TemplateSegmentHandler -->
Somia.Web.Routing.Template.ITemplateIterator iterator -->
Somia.Web.Routing.Template.ITemplateIterator
I ended up implementing IMethodQuery and select the ctor I wanted.
public sealed class SelectedFirstConstructorQuery : IMethodQuery
{
private readonly Type _type;
public SelectedFirstConstructorQuery(Type type)
{
_type = type;
}
public IEnumerable<IMethod> SelectMethods(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
return from ci in type.GetConstructors()
let parameter = ci.GetParameters().First()
where parameter.ParameterType == _type
select new ConstructorMethod(ci) as IMethod;
}
}
Usage:
fixture.Customize<TemplateSegmentHandler>(c => c.FromFactory(new MethodInvoker(new SelectedFirstConstructorQuery(typeof(ITemplateParameterHandler)))));
One possible way:
var parameterHandler = fixture.Create<ITemplateParameterHandler>();
var segmentHandler = fixture.Build<TemplateSegmentHandler>()
.FromFactory(() => new TemplateSegmentHandler(parameterHandler));
fixture.Inject(segmentHandler);

how to stub out an IEntityRepository

im trying to stub the following line of code in C# using rhino mocks although unsuccessfully. Any suggestions please? This is the line that causes the test to fail
var header = this.repository.Headers.FirstOrDefault(h => h.Id == id);
Full details below, many thanks!
Unit test
private IRepository _repository;
[TestInitialize]
public void SetUp()
{
_repository = _mockRepository.Stub<IRepository>();
_commandService = new CoreCommandService(_repository);
}
[TestMethod]
public void MyTest()
{
// Line that doesn't work
_repository.Stub(x => x.Headers).Return(SomeThing);
}
implementation
// The Headers is stubbed although Id is null
var header = this.repository.Headers.FirstOrDefault(h => h.Id == id);
public interface IRepository
{
IEntityRepository<Header> Headers { get; }
}
UPDATE #1
public interface IEntityRepository<TEntity> : IQueryable<TEntity>, IDisposable where TEntity : class
UPDATE #2
Using the following example
var wrapper = new HeadersWrapper(...);
_repository.Stub(x => x.Headers).Return(wrapper);
Returns the following message when compiling
HeaderWrapper is not assignable to parameter type IEntityRepository<Header>
Difficult.
I think you have two options.
If you can change the return type of Headers from IEntityRepository<T> to IQueryable<T>, you can return a queryable List<T> for Headers:
IList<T> list = new List<Header> { /* Some Header object */ }
IQueryable<T> queryableList = list.AsQueryable();
_repository.Stub(x => x.Headers).Return(queryableList);
If you can't change the return type, you need to create a test fake (a new class) that derives from IEntityRepository<T>, and wraps a queryable List<T>. You will need to implement all the methods that IEntityRepository<T> and its interfaces define, but just call the relevant function on the queryable List<T>. Then you add a relevant Header to the underlying queryable List<T> as above and return a new instance of this object to stub Headers.
IQueryable<Header> Wrapper would look something like this:
public class HeadersWrapper : IQueryable<Header>
{
private readonly IQueryable<Header> _queryableSource;
public HeadersWrapper(IEnumerable<Header> source)
{
_queryableSource = source.AsQueryable();
}
public IEnumerator<Header> GetEnumerator()
{
return _queryableSource.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Expression Expression
{
get { return _queryableSource.Expression; }
}
public Type ElementType
{
get { return _queryableSource.ElementType; }
}
public IQueryProvider Provider
{
get { return _queryableSource.Provider; }
}
}
And you'd use it something like this:
var headers = new List<Header>
{
new Header { Id = "foo" }
};
var wrapper = new HeadersWrapper(headers);
repo.Stub(x => x.Headers).Return(wrapper);
And of course, you can exchange IQueryable<Header> for IEntityRepository<Header> if you want to.

Categories

Resources