Multiple interceptors in NHibernate - c#

I am very new to NHibernate and have been following various tutorials online, especially this one to create my own program. I really liked the use of the interceptor to add INotifyPropertyChanged to entities created using the DataBindingFactory and tried to follow the same idea to add IDataErrorInfo to entities created by the DataBindingFactory with another method CreateWithValidation(Type type):
public static object CreateWithValidation(Type type)
{
return _proxyGenerator.CreateClassProxy(type, new[]
{
typeof (IDataErrorInfo),
typeof (INotifyPropertyChanged)
}, new IInterceptor[]
{
new NotifyPropertyChangedInterceptor(type.FullName),
new DataErrorInfoInterceptor()
});
}
The code for the NotifyPropertyChangedInterceptor is the same as in the linked article and below is my implementation of the DataErrorInfoInterceptor class which came from this article:
public class DataErrorInfoInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
{
var validator = new ValidatorEngine();
var errors = validator.Validate(invocation.Proxy);
if (invocation.Method.Name.Equals("get_Item"))
{
String propertyName = Convert.ToString(invocation.Arguments[0]);
var propertyErrors = errors
.Where(e => e.PropertyName.Equals(propertyName))
.Select(e => e.Message)
.ToArray();
if (propertyErrors.Count() > 0)
{
invocation.ReturnValue = string.Join(Environment.NewLine, propertyErrors);
}
else
{
invocation.ReturnValue = null;
}
}
else if (invocation.Method.Name.Equals("get_Error"))
{
var allErrors = errors
.Select(e => e.Message)
.ToArray();
if (allErrors.Count() > 0)
{
invocation.ReturnValue = string.Join(Environment.NewLine, allErrors);
}
else
{
invocation.ReturnValue = null;
}
}
else
{
invocation.Proceed();
}
}
}
The problem that I have is that if I create an object using the CreateWithValidation() method and use it on a model, any text I enter into a textbox on the view is cleared when I tab away from the field (this probably happens in other fields as well but I've only tried it on textboxes). I suspect that this is because both of the classes implementing IInterceptor have the line invocation.Proceed() if the method that has been intercepted is not one that the class is interested in.
My question is, is it possible to have two interceptors like this or do I have to have one massive class, eg: CustomInterceptor which has all of the methods for, eg: INotifyPropertyChanged and IDataErrorInfo and deal with them there? That seems quite unwieldy to me.
For what it's worth, this is how I set the interceptor on my SessionFactory:
public static void Initialise()
{
Configuration config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c
.Server("")
.Database("")
.Username("")
.Password("")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Map>()
.Conventions.AddFromAssemblyOf<EnumConvention>())
.BuildConfiguration();
ConfigureNhibernateValidator(config);
DataBindingInterceptor interceptor = new DataBindingInterceptor();
SessionFactory = config
.SetInterceptor(interceptor)
.BuildSessionFactory();
}

The problem is not multiple interceptors. And the problem is not calling invocation.Proceed(). The problem is that you don't call invocation.Proceed() in your DataErrorInfoInterceptor when the method is not from IDataErrorInfo (it's correct in the linked article). Because of this, when you call some getter or setter, nothing happens.
Right now, you have something like this:
if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
{
if (invocation.Method.Name.Equals("get_Item"))
{
// some code
}
else if (invocation.Method.Name.Equals("get_Error"))
{
// more code
}
else
{
invocation.Proceed();
}
}
What you should have is this:
if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
{
if (invocation.Method.Name.Equals("get_Item"))
{
// some code
}
else if (invocation.Method.Name.Equals("get_Error"))
{
// more code
}
}
else
{
invocation.Proceed();
}
Next time, try stepping through the code in debugger to see what's really going on.

Related

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);

Strange control flow

I'm working on a framework in C# that will depend on pluggable components implemented as classes inheriting a base class. In order to make the components as simple as possible, I am working on some weird control flow.
The base class includes a static method RunStep(parameter). This method is called a number of times by the inheriting class, and each time it is called a condition is checked. If this condition happens to be false, I want the calling method to stop and return. A simplified working version of the code would be:
Base class:
class MyBase
{
private static object RunStep(string parameter)
{
if(SomeFunction(parameter))
return SomeOtherFunction(parameter);
else
return null;
}
}
Inheriting class:
class MyInheritor
{
public void Run()
{
object result = RunStep("mystring1");
if(null != result)
{
//perform some logic on result
result = RunStep("mystring2");
if(null != result){
//perform some different logic on result
RunStep("mystring3");
}
}
}
}
What I am wondering is whether it is possible to do something in the base class so that I can simplify the inheriting class to this:
class MyInheritor2
{
public void Run()
{
object result = RunStep("mystring1");
//perform some logic on result
result = RunStep("mystring2");
//perform some different logic on result
result = RunStep("mystring3");
}
}
}
I would put the parameters in a list and loop over them, but there is logic that needs to happen after each call to the RunStep method, and the logic is different each time. This takes a loop off the table. Also note that the logic between the RunStep calls accesses properties on result, so it crashes without the null checks.
It may seem like a trivial thing, but there may be thousands of these Inheriting classes and simplifying them is a big deal.
Let the base class to control the execution flow:
class Base
{
private readonly List<Tuple<string, Action>> steps = new List<Tuple<string, Action>>();
protected void RegisterStep(string parameter, Action someLogic)
{
steps.Add(Tuple.Create(parameter, someLogic));
}
protected void Run()
{
foreach (var step in steps)
{
var result = RunStep(step.Item1);
if (result == null)
{
break;
}
// perform some logic
step.Item2();
}
}
private object RunStep(string parameter)
{
// some implementation
return null;
}
}
class Derived : Base
{
public Derived()
{
RegisterStep("1", () => { });
RegisterStep("2", () => { });
RegisterStep("3", () => { });
// etc
}
}
There's no way to make a function call exit the calling function except for throwing an Exception, which you shouldn't do.
What you can do to make your code cleaner is to invert the cases.
object result = RunStep("mystring1");
if (result == null) return;
result = RunStep("mystring2");
if (result == null) return;
result = RunStep("mystring3");
if (result == null) return;

Validating model properties WCF Web APi

I have a set of services hosted with WCF Web Api, what I need to do is validate the properties inside the models of the app.
In MVC 3 for example I decorate properties in the model like this:
[StringLength(30)]
public string UserName { get; set; }
and then in the controller I proceed like this to verify os the model has met the validation parameters:
[HttpPost]
ActionResult Create(Model myModel)
{
if(ModelState.IsValid(){
Post the model
}
else
{
Don't post the model
}
}
Is there a way to do something similar in WCF Web Api?
Ok I finally managed to get validations for my models working. I wrote a validation handler and a couple of extensions methods. First thing the validation handler:
public class ValidationHandler<T> : HttpOperationHandler
{
private readonly HttpOperationDescription _httpOperationDescription;
public ValidationHandler(HttpOperationDescription httpOperationDescription)
{
_httpOperationDescription = httpOperationDescription;
}
protected override IEnumerable<HttpParameter> OnGetInputParameters()
{
return _httpOperationDescription.InputParameters
.Where(prm => prm.ParameterType == typeof(T));
}
protected override IEnumerable<HttpParameter> OnGetOutputParameters()
{
return _httpOperationDescription.InputParameters
.Where(prm => prm.ParameterType == typeof(T));
}
protected override object[] OnHandle(object[] input)
{
var model = input[0];
var validationResults = new List<ValidationResult>();
var context = new ValidationContext(model, null, null);
Validator.TryValidateObject(model, context, validationResults,true);
if (validationResults.Count == 0)
{
return input;
}
else
{
var response = new HttpResponseMessage()
{
Content = new StringContent("Model Error"),
StatusCode = HttpStatusCode.BadRequest
};
throw new HttpResponseException(response);
}
}
}
Notice how the Handler receives a T object, this is mainly because I would like to validate all the model types within the API. So the OnGetInputParameters specifies that the handler needs to receive a T type object, and the OnGetOutputParameters specifies that the handler needs to return an object with the same T type in case validations policies are met, if not, see how the on handle method throws an exception letting the client know that there's been a validation problem.
Now I need to register the handler, for this I wrote a couple of extensions method, following an example of a Pedro Felix's blog http://pfelix.wordpress.com/2011/09/24/wcf-web-apicustom-parameter-conversion/ (this blog helped me a lot, there are some nice explanations about the whole handler operations thing). So these are the extensions methods:
public static WebApiConfiguration ModelValidationFor<T>(this WebApiConfiguration conf)
{
conf.AddRequestHandlers((coll, ep, desc) =>
{
if (desc.InputParameters.Any(p => p.ParameterType == typeof(T)))
{
coll.Add(new ValidationHandler<T>(desc));
}
});
return conf;
}
so this methos checks if there is a T type parameter in the operations, and if so, it adds the handler to that specific operation.
This one calls the other extension method AddRequestHandler, and that method add the new handler without removing the previous registered ones, if the exist.
public static WebApiConfiguration AddRequestHandlers(
this WebApiConfiguration conf,
Action<Collection<HttpOperationHandler>,ServiceEndpoint,HttpOperationDescription> requestHandlerDelegate)
{
var old = conf.RequestHandlers;
conf.RequestHandlers = old == null ? requestHandlerDelegate :
(coll, ep, desc) =>
{
old(coll, ep, desc);
};
return conf;
}
The last thing is to register the handler:
var config = new WebApiConfiguration();
config.ModelValidationFor<T>(); //Instead of passing a T object pass the object you want to validate
routes.SetDefaultHttpConfiguration(config);
routes.MapServiceRoute<YourResourceObject>("SomeRoute");
So this is it.. Hope it helps somebody else!!
I am currently working on a HttpOperationHandler that does exactly what you need. It's not done by now, but this psuedo code might give you an idea of how you can do it.
public class ValidationHandler : HttpOperationHandler
{
private readonly HttpOperationDescription _httpOperationDescription;
private readonly Uri _baseAddress;
public ValidationHandler(HttpOperationDescription httpOperationDescription, Uri baseAddress)
{
_httpOperationDescription = httpOperationDescription;
_baseAddress = baseAddress;
}
protected override IEnumerable<HttpParameter> OnGetInputParameters()
{
return new[] { HttpParameter.RequestMessage };
}
protected override IEnumerable<HttpParameter> OnGetOutputParameters()
{
var types = _httpOperationDescription.InputParameters.Select(x => x.ParameterType);
return types.Select(type => new HttpParameter(type.Name, type));
}
protected override object[] OnHandle(object[] input)
{
var request = (HttpRequestMessage)input[0];
var uriTemplate = _httpOperationDescription.GetUriTemplate();
var uriTemplateMatch = uriTemplate.Match(_baseAddress, request.RequestUri);
var validationResults = new List<ValidationResult>();
//Bind the values from uriTemplateMatch.BoundVariables to a model
//Do the validation with Validator.TryValidateObject and add the results to validationResults
//Throw a exception with BadRequest http status code and add the validationResults to the message
//Return an object array with instances of the types returned from the OnGetOutputParmeters with the bounded values
}
}
The OnGetInputParameters value tells what's expected into the OnHandle method, and the OnGetOutputParameters tells what's the expected output from the OnHandle method (which later on is injected into the method in the service).
You can then add the handler to the routing with a HttpConfiguration as follows:
var httpConfiguration = new HttpConfiguration
{
RequestHandlers = (collection, endpoint, operation) => collection.Add(new ValidationHandler(operation, endpoint.Address.Uri))
};
RouteTable.Routes.MapServiceRoute<MyResource>("MyResource", httpConfiguration);
There is an example of this posted on MSDN of creating a behavior for this that should work. You could also call the validators manually with Validator.ValidateObject (or wrap it as an extension method) and return the validation errors, which is essentially what that behavior is doing.
Firstly I should say awesome question+answer Daniel
However, I've taken it a little further, refined it and added to it.
ValidationHander
I've refined this a little. It is now based on a generic HttpOperationHandler so it can take the HttpRequestMessage. The reason for this is so that I can return error messages formatted using the correct media type (from the accept header).
public class ValidationHandler<TResource> : HttpOperationHandler<TResource, HttpRequestMessage, HttpRequestMessage>
{
public ValidationHandler() : base("response") { }
protected override HttpRequestMessage OnHandle(TResource model, HttpRequestMessage requestMessage)
{
var results = new List<ValidationResult>();
var context = new ValidationContext(model, null, null);
Validator.TryValidateObject(model, context, results, true);
if (results.Count == 0)
{
return requestMessage;
}
var errorMessages = results.Select(x => x.ErrorMessage).ToArray();
var mediaType = requestMessage.Headers.Accept.FirstOrDefault();
var response = new RestValidationFailure(errorMessages);
if (mediaType != null)
{
response.Content = new ObjectContent(typeof (string[]), errorMessages, mediaType);
}
throw new HttpResponseException(response);
}
}
Extension Methods
The 2 you provided stay virtually the same about from the desc paramter no longer being needed when adding the ValidationHandler in the ModelValidationFor method
I've added an extra extension method. This is to make sure that all "Resource" classes are validated. This is mainly me being lazy and forgetful. I am forever forgetting to add some class to a list somewhere. (It's why I write generic windsor installers!)
public static void ValidateAllResourceTypes(this WebApiConfiguration config, string assemblyFilter = "MyCompany*.dll")
{
var path = Path.GetDirectoryName((new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
var dc = new DirectoryCatalog(path, assemblyFilter);
var assemblies = dc.LoadedFiles.Select(Assembly.LoadFrom).ToList();
assemblies.ForEach(assembly =>
{
var resourceTypes = assembly.GetTypes()
.Where(t => t.Namespace != null && t.Namespace.EndsWith("Resources"));
foreach (var resourceType in resourceTypes)
{
var configType = typeof(Extensions);
var mi = configType.GetMethod("ModelValidationFor");
var mi2 = mi.MakeGenericMethod(resourceType);
mi2.Invoke(null, new object[] { config });
}
});
}
I made use of the System.ComponentModel.Composition.Hosting namespace (formerly known as MEF) for the DirectoryCatalog class. In this case I've just used the namespace ending with "Resources" to find my "Resource" classes. It wouldn't take much work to change it to use a custom attribute or whatever other way you might prefer to identify which classes are your "Resources".
RestValidationFailure
This is a little helper class I made to allow consistent behaviour for validation failure responses.
public class RestValidationFailure : HttpResponseMessage
{
public RestValidationFailure(string[] messages)
{
StatusCode = HttpStatusCode.BadRequest;
foreach (var errorMessage in messages)
{
Headers.Add("X-Validation-Error", errorMessage);
}
}
}
So, now I get a nice list (in my preferred mediatype) of all the validation errors.
Enjoy! :)

How can I use a mock when the code validates the types it receives

I want to test the following code:
public IEnumerable<KeyValuePair<Fact, Exception>> ValidateAll()
{
//...do something
var invalidFacts = GetInvalidFacts();
//...do something
return duplicateFacts.Concat(invalidFacts);
}
private IEnumerable<KeyValuePair<Fact, Exception>> GetInvalidFacts()
{
var invalidFacts = Facts.Select(fact =>
{
try
{
fact.Validate();
return new KeyValuePair<Fact, Exception>(fact, null);
}
catch (FormatException e)
{
return new KeyValuePair<Fact, Exception>(fact, e);
}
catch (Exception e)
{
return new KeyValuePair<Fact, Exception>(fact, e);
}
}).Where(kv => kv.Value != null).ToList();
return invalidFacts;
}
Basically the test's objective is to verify that all objects that exist within the "Facts" IEnumerable will call their Validate method. Since I'm not interested to test the code within those objects, there are already lots of tests that do that, I want to inject a list of fake facts. I'm using MOQ to create the fakes.
So my unit test looks like this:
[TestMethod]
public void ValidateAll_ValidateMethodIsInvokedOnAllFacts_WhenCalled()
{
var anyFactOne = new Mock<Fact>(); //Fact is an abstract class.
anyFactOne.Setup(f => f.Validate());
var dataWarehouseFacts = new DataWarehouseFacts { Facts = new Fact[] { anyFactOne.Object, FactGenerationHelper.GenerateRandomFact<SourceDetails>() } };
dataWarehouseFacts.ValidateAll();
}
Now I'm getting an exception because the code is actually validating the kind of Facts that can be injected to the DataWarehouseFacts class, like so:
public IEnumerable<Fact> Facts
{
get
{
.....
}
set
{
var allowedTypes = new []
{
typeof(ProductUnitFact),
typeof(FailureFact),
typeof(DefectFact),
typeof(ProcessRunFact),
typeof(CustomerFact),
typeof(ProductUnitReturnFact),
typeof(ShipmentFact),
typeof(EventFact),
typeof(ComponentUnitFact),
typeof(SourceDetails)
};
if(!value.All(rootFact => allowedTypes.Contains(rootFact.GetType())))
throw new Exception ("DataWarehouseFacts can only be set with root facts");
ProductUnitFacts = value.OfType<ProductUnitFact>().ToList();
FailureFacts = value.OfType<FailureFact>().ToList();
DefectFacts = value.OfType<DefectFact>().ToList();
ProcessRunFacts = value.OfType<ProcessRunFact>().ToList();
CustomerFacts = value.OfType<CustomerFact>().ToList();
ProductUnitReturnFacts = value.OfType<ProductUnitReturnFact>().ToList();
ShipmentFacts = value.OfType<ShipmentFact>().ToList();
EventFacts = value.OfType<EventFact>().ToList();
ComponentUnitFacts = value.OfType<ComponentUnitFact>().ToList();
SourceDetails = value.OfType<SourceDetails>().Single();
}
}
What would be the best way to get around this validation?
Thanks.
The two obvious methods that leap to mind are:
Add Fact to your list of allowed types.
Moq one of your allowed fact types rather than the base Fact class itself. (I presume that your Validate() method is overrideable.)
Another slightly more complicated option would be to inject your list of allowed types at test time, assuming you have control over the DataWarehouseFacts class. That might look something like this:
class DWF
{
static IEnumerable<Fact> defaultAllowedFacts = new Fact[] { ... }
IEnumerable<Fact> allowedFacts;
public DWF() : this(defaultAllowedFacts) { ... }
internal DWF(IEnumerable<Fact> allowed)
{
// for testing only, perhaps
this.allowedFacts = allowed;
}
...
}
Then just delete that var allowedTypes = new [] bit and use this.allowedFacts instead.
I would leverage Type.IsAssignableFrom
E.g. instead of saying
allowedTypes.Contains(v.GetType())
I'd say
allowedTypes.Any(t => t.IsAssignableFrom(v.GetType()))
That way you can pass proper subclasses just as well as the exact matching types. Perhaps, maybe, that was what you were after with the typelist itself?
First of all I want to thank both ladenedge (I did gave a +1 to his answer) and sehe for their answers. Even though it was not exactly what I was looking for they are interesting ideas to keep in mind.
I couldn't just add the Fact class to the list of allowed types since that would have opened the door for lots of classes that should not be allowed; there are about 30 classes inheriting from it.
So what I ended up doing was to extract the code from the set part of the Facts property in their own methods and made one of them protected virtual, like so:
public IEnumerable<Fact> Facts
{
get
{
...
}
set
{
ValidateReceived(value);
ExtractFactTypesFrom(value.ToList());
}
}
protected virtual void ValidateReceived(IEnumerable<Fact> factTypes)
{
if (factTypes == null) throw new ArgumentNullException("factTypes");
var allowedTypes = GetAllowedFactTypes();
if (!factTypes.All(rootFact => allowedTypes.Contains(rootFact.GetType()))) throw new Exception("DataWarehouseFacts can only be set with root facts");
}
private IEnumerable<Type> GetAllowedFactTypes()
{
var allowedTypes = new[]
{
typeof (ProductUnitFact),
typeof (SequenceRunFact),
typeof (FailureFact),
typeof (DefectFact),
typeof (ProcessRunFact),
typeof (CustomerFact),
typeof (ProductUnitReturnFact),
typeof (ShipmentFact),
typeof (EventFact),
typeof (ComponentUnitFact),
typeof (SourceDetails)
};
return allowedTypes;
}
private void ExtractFactTypesFrom(List<Fact> value)
{
ProductUnitFacts = value.OfType<ProductUnitFact>().ToList();
FailureFacts = value.OfType<FailureFact>().ToList();
DefectFacts = value.OfType<DefectFact>().ToList();
ProcessRunFacts = value.OfType<ProcessRunFact>().ToList();
SequenceRunFacts = value.OfType<SequenceRunFact>().ToList();
CustomerFacts = value.OfType<CustomerFact>().ToList();
ProductUnitReturnFacts = value.OfType<ProductUnitReturnFact>().ToList();
ShipmentFacts = value.OfType<ShipmentFact>().ToList();
EventFacts = value.OfType<EventFact>().ToList();
ComponentUnitFacts = value.OfType<ComponentUnitFact>().ToList();
SourceDetails = value.OfType<SourceDetails>().Single();
}
That way I was able to create a DataWarehouseFactsForTest and override the ValidateReceived method so it wouldn't do anything:
public class DataWarehouseFactsForTests : DataWarehouseFacts
{
protected override void ValidateReceived(IEnumerable<Fact> factTypes)
{}
}
That way I was able to to use Moq to create the Facts and verify the code within the private GetInvalidFacts method. For example:
[TestMethod]
public void ValidateAll_ReturnsADictionaryWithAFormatException_WhenOneOfTheFactsValidationThrowsAFormatException()
{
var anyFactOne = new Mock<ProductUnitFact>();
var anyFactTwo = new Mock<SequenceRunFact>();
var anyFactThree = new Mock<SourceDetails>();
anyFactOne.Setup(f => f.Validate()).Throws(new FormatException());
var dataWarehouseFacts = new DataWarehouseFactsForTests { Facts = new Fact[] { anyFactOne.Object, anyFactTwo.Object, anyFactThree.Object } };
var result = dataWarehouseFacts.ValidateAll().ToList();
anyFactOne.Verify(f => f.Validate(), Times.Exactly(1));
anyFactTwo.Verify(f => f.Validate(), Times.Exactly(1));
anyFactThree.Verify(f => f.Validate(), Times.Exactly(1));
Assert.AreEqual(1, result.Count());
Assert.AreEqual(typeof(FormatException), result.First().Value.GetType());
}

Unity to Structure Map

I am trying out the code from this post on Event Driven Architecture (very interesting by the way). His IOC container is Unity though and I would like to do this using Structure map.
His code is:
public class EventSubscriptions : ISubscriptionService
{
public static void Add<T>()
{
var consumerType = typeof(T);
consumerType.GetInterfaces()
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == typeof(IConsumer<>))
.ToList()
.ForEach(x => IoC.Container.RegisterType(x,
consumerType,
consumerType.FullName));
}
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = IoC.Container.ResolveAll(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
I have the following which does not seem to be working:
public class SubscriptionService : ISubscriptionService
{
public static void Add<T>()
{
var consumerType = typeof(T);
consumerType.GetInterfaces()
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == typeof (IConsumer<>))
.ToList().ForEach(x => ObjectFactory.Inject(consumerType, x));
}
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = ObjectFactory.GetAllInstances(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
I am obviously not too familiar with Structure Map. Some links or explanation on what I am doing wrong would be really appreciated.
Update:
From Henning's answer, I ended up with -
public class SubscriptionService : ISubscriptionService
{
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = ObjectFactory.GetAllInstances(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
And then in my bootstrapping class that is called on application startup I have:
public static void ConfigureStuctureMap()
{
ObjectFactory.Initialize(x =>
{
x.Scan(y =>
{
y.Assembly("Domain");
y.Assembly("Website");
y.AddAllTypesOf(typeof(IConsumer<>));
y.WithDefaultConventions();
});
});
}
Although I'm not a structuremap expert, I do believe you can do it in another way.
Structuremap has the ability to scan any given assembly for a given interface and automatically register all the implementations. We do that in my current project and it works really great.
I don't remember the exact code we use, but you can check out the documentation for assembly scanning
http://structuremap.sourceforge.net/ScanningAssemblies.htm
Build custom TypeScanner class that implement ITypeScanner interface.
public class EventSubConventionScanner : ITypeScanner
{
public void Process(Type type, PluginGraph graph)
{
Type interfaceType = type.FindInterfaceThatCloses(typeof(IConsumer<>));
if (interfaceType != null)
{
graph.AddType(interfaceType, type);
}
}
}
After, in registry or initialize routine write:
Scan(x =>
{
x.With<EventSubConventionScanner>();
});

Categories

Resources