RhinoMocks stubs with simplified implementation, Try-method pattern - c#

I want to mock a quite huge repository with RhinoMocks, mainly for the purpose of fully implementing a huge and frequently changing interface, just instead of using VisualStudio's "Implement Interface" default implementation (which requires all mocks to be updated for an interface change and causes a lot of junk code).
I currently use Stubs, but I haven't found out how to override mocked default methods, except defining every possible input value. This is especially bad when using the bool TryGet(key, out value) pattern and when I need a default behaviour besides, if the key is not found (here: return false/null, in other cases: throw exception).
Is there any way to implement method forwarding in RhinoMocks?
public interface IMyRepository
{
// would normally be implemented by database access
bool TryGetNameById(int id, out string name);
// more...
}
// within some other class:
public void SetupMockRepository()
{
IDictionary<int, string> namesByIds = new Dictionary<int, string>()
//create and fill with mock values
var mockRep = new MockRepository()
var repStub = mockRep.Stub<IMyRepository>()
// something like this, forward inner calls,
// without defining expected input values
var repStub.Stub(r => r.TryGetNameById(int id, out string name)
.OutRef((id) => (namesByIds.TryGetValue(id, out name) ? name : null))
.Return((id) => namesByIds.ContainsKey(id)));
}
EDIT:
I tried a delegate now, which looks better, but still has problems:
private delegate bool TryGet<TKey, TValue>(TKey key, out TValue value);
public void SetupMockRepository()
{
// code from above omitted
string outName;
_stub.Stub(r=>r.TryGetNameById(0, out outName))
.IgnoreArguments()
.Do(new TryGet<int,string>(namesByIds.TryGetValue))
}
This is accepted, but when I run it, I get an InvalidOperationException:
"Previous method 'TryGetValue(123)' requires a return value or an exception to throw"

You can always make your own fake objects. With a mix of that and partial mocks, you should gain a maximum of flexibility.
public interface IMyRepository
{
bool TryGetNameById(int id, out string name);
}
public class FakeRepository : IMyRepository
{
// public on purpose, this is for testing after all
public readonly Dictionary<int, string> nameByIds = new Dictionary<int, string>();
// important to make all methods/properties virtual that are part of the interface implementation
public virtual bool TryGetNameById(int id, out string name)
{
return this.nameByIds.TryGetValue(id, out name);
}
}
Your setup would become this then:
public void Setup()
{
var mock = MockRepository.GeneratePartialMock<FakeRepository>();
mock.nameByIds.Add(1, "test");
}
And if you need more sophisticated behavior, you can still stub method calls since all methods are virtual.

Here's my first, partial solution:
The mock object required a .Replay() after the delegate settings, because the methods were used before MockRep.ReplayAll() was called (before the test itself).
I currently use expectations and record/replay logic only in few cases (and do not fully comprehend what it is like), and it is disturbing to find the mock objects fail on seemingly correct settings. I just want a default implementation with a few overridden methods/properties, which does not cause build failures if somebody changes unrelated parts of the interface.
Another, new problem is that setting up a .Do() delegate like
mockObj.Stub(o => o.DoSth(x))
.IgnoreArguments()
.Do(new Action(x => this.DoSth(x)))
causes an expectation error on a completely different method, which has default stub implementation and not been changed.

Related

Strategy Pattern with each algorithm having a different method signature

I am doing a refactor over certain code.
We have a list of investors with amounts assigned to each. The total of amounts should be equal to another total, but sometimes there are a couple of cents of difference, so we use different algorithms to assign these differences to each investor.
The current code is something like this:
public void Round(IList<Investors> investors, Enum algorithm, [here goes a list of many parameters]) {
// some checks and logic here - OMMITED FOR BREVITY
// pick method given algorithm Enum
if (algoritm == Enum.Algorithm1) {
SomeStaticClass.Algorithm1(investors, remainders, someParameter1, someParameter2, someParameter3, someParameter4)
} else if (algoritm == Enum.Algorithm2) {
SomeStaticClass.Algorithm2(investors, remainders, someParameter3)
}
}
so far we only have two algorithms. I have to implement the third one. I was given the possibility to refactor both existing implementations as well as do some generic code to make this function for future algorithms, maybe custom to each client.
My first thought was "ok, this is a strategy pattern". But the problem I see is that both algorithms receive a different parameter list (except for the first two). And future algorithms can receive a different list of parameters as well. The only thing in "common" is the investor list and the remainders.
How can I design this so I have a cleaner interface?
I thought of
Establishing an interface with ALL possible parameters, and share it
among all implementations.
Using an object with all possible parameters as properties, and use that generic object as part of the interface. I
would have 3 parameters: The list of investors, the remainders object, and a "parameters" object. But in this case, I have a similar problem. To instantiate each object and fill the required properties depends on the algorithm (unless I set all of them). I
would have to use a factory (or something) to instantiate it, using all parameters in the interface, am I right? I would be moving the problem of too many parameters to that "factory" or whatever.
Using a dynamic object instead of a statically typed object. Still
presents the same problems as before, the instantiation
I also thought of using the Visitor Pattern, but as I understand, that would be the case if I had different algorithms for different entities to use, like, another class of investors. So I don't think it is the right approach.
So far the one that convinces me the most is the second, although I am still a bit reticent about it.
Any ideas?
Thanks
Strategy has different implementations. Its straightforward when all alternate Concrete Strategies require same type signature. But when concrete implementations start asking for different data from Context, we have to gracefully take a step back by relaxing encapsulation ("breaking encapsulation" is known drawback of strategy), either we can pass Context to strategies in method signature or constructor depending upon how much is needed.
By using interfaces and breaking big object trees in to smaller containments we can restrict the access to most of the Context state.
following code demonstrates passing through method parameter.
public class Context {
private String name;
private int id;
private double salary;
Strategy strategy;
void contextInterface(){
strategy.algorithmInterface(this);
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public double getSalary() {
return salary;
}
}
public interface Strategy {
// WE CAN NOT DECIDE COMMON SIGNATURE HERE
// AS ALL IMPLEMENTATIONS REQUIRE DIFF PARAMS
void algorithmInterface(Context context);
}
public class StrategyA implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getName();
context.getId();
}
}
public class StrategyB implements Strategy{
#Override
public void algorithmInterface(Context context) {
// OBSERVE HERE BREAKING OF ENCAPSULATION
// BY OPERATING ON SOMEBODY ELSE'S DATA
context.getSalary();
context.getId();
}
}
Okay, I might be going in the wrong direction... but it seems kinda weird that you're passing in arguments to all the algorithms, and the identifier to which algorithm to actually use. Shouldn't the Round() function ideally just get what it needs to operate?
I'm imagining the function that invokes Round() to look something like:
if (something)
algToUse = Enum.Algorithm1;
else
if (otherthing)
algToUse = Enum.Algorithm2;
else
algToUse = Enum.Algorithm3;
Round(investors, remainder, algToUse, dayOfMonth, lunarCycle, numberOfGoblinsFound, etc);
... what if, instead, you did something like this:
public abstract class RoundingAlgorithm
{
public abstract void PerformRounding(IList<Investors> investors, int remainders);
}
public class RoundingRandomly : RoundingAlgorithm
{
private int someNum;
private DateTime anotherParam;
public RoundingRandomly(int someNum, DateTime anotherParam)
{
this.someNum = someNum;
this.anotherParam = anotherParam;
}
public override void PerformRounding(IList<Investors> investors, int remainder)
{
// ... code ...
}
}
// ... and other subclasses of RoundingAlgorithm
// ... later on:
public void Round(IList<Investors> investors, RoundingAlgorithm roundingMethodToUse)
{
// ...your other code (checks, etc)...
roundingMethodToUse.Round(investors, remainders);
}
... and then your earlier function simply looks like:
RoundingAlgorithm roundingMethod;
if (something)
roundingMethod = new RoundingByStreetNum(1, "asdf", DateTime.Now);
else
if (otherthing)
roundingMethod = new RoundingWithPrejudice(null);
else
roundingMethod = new RoundingDefault(1000);
Round(investors, roundingMethod);
... basically, instead of populating that Enum value, just create a RoundingAlgorithm object and pass that in to Round() instead.

Factory Pattern, selecting by Property

I have a (growing) list of Data-Generators. The generator that I need is created by a factory class. The generators all implement a common Interface, which includes among other things a static string name.
What I would like to do: Call the factory.Create method with a string parameter for the above mentioned name. The create method finds the generator with this name and returns a new instance of said generator.
Bonus in my opinion of this way to do it: I only have to add new generator classes without having to edit the factory.
Question:
Is this a good way to handle this problem?
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Is it correct to call this way of working a factory, or is this some different pattern?
In the end I would call the factory like this (simplified):
//Caller
public DataModel GetData2()
{
var generator = new DataFactory().Create("Gen.2");
return generator.GetData();
}
//Factory
public class DataFactory
{
public AbstractDataGenerator Create(string type)
{
//Here the magic happens to find all implementations of IDataGenerator
var allGenerators = GetImplementations();
var generator = allGenerators.FirstOrDefault(f => f.name == type);
if (generator != null)
return (AbstractDataGenerator)Activator.CreateInstance(generator);
else
return null;
}
}
//Interface
public abstract class AbstractDataGenerator
{
public static string name;
public abstract DataModel GetData();
}
//Data-Generators
public class DataGen1 : AbstractDataGenerator
{
public static string name = "Gen.1";
public DataModel GetData()
{
return new DataModel("1");
}
}
public class DataGen2 : AbstractDataGenerator
{
public static string name = "Gen.2";
public DataModel GetData()
{
return new DataModel("2");
}
}
Should the magic GetImplementations() in the factory be done via Reflection or somehow different? Should I use a completely different approach?
Since answers refer to IoC and DI: This project uses NInject already, so it would be available.
Switched from interface to abstract class.
Is this a good way to handle this problem?
Having a factory to get an instance of the logic class you need by some key - I believe it is a good way. It is a pattern that I use a lot myself. About the way you have your key - I'd prefer to not have it as a static member (regardless to the fact that interfaces can't have static members) but just as a property and to add a base class to the IDataGenerator. That base class will have a constructor that will get the name - That way each new DataGenerator you create will have to set it and you wont forget.
About having the name as a string - I personally prefer having it "strongly typed". What I mean is that if I pass Gen . 2 instead of Gen.2 with strings I will discover this problem only in runtime. Possible other ways (if you want, because a simple string is fine too - a matter of taste):
Replace strings with an enum
Have a static class with static readonly strings for all your values - then in your code use those values. You get the benifits of the intellisense and of not getting the string wrong but better than enum - you can just still pass strings that are not in the "list" so you can add new ones as add-ons.
Have a RequestGenerator object, with each Generator being IDataGenerator<TGeneratorRequest>. This might be an overkill but if you have also extra information you need for the creating of a DataGenerator which differs between them then consider it .
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Yes, reflection can be a good way to do so. However, I would suggest to read into Dependency Injection and IoC Containers like Castle Windsor for example. There are things out there that already implement it for you, so why to re-invent the wheel :)
DI is a life changer concept in my opinion
Is it correct to call this way of working a factory, or is this some different pattern?
Yap. It is a Factory
Should the magic GetImplementations() in the factory be done via Reflection or somehow different?
See answer for question 2
This is where constructor injection can REALLY shine. Look into dependency injection tools and employ one! It also checks your "Bonus" request.
Here's what your factory might look like with constructor injection:
public class DataFactory
{
private Dictionary<string, IDataGenerator> generators;
public DataFactory(IDataGenerator[] generatorReferences)
{
this.generators = generatorReferences
.ToDictionary(k => k.name, v => v);
}
public IDataGenerator Create(string type)
{
IDataGenerator generator = null;
this.generators.TryGetValue(type, out generator);
return generator;
}
}
Most DI software has the capability to automatically scan assemblies for implementations of a certain type (e.g. IDataGenerator) and register those with itself, when it constructs an instance of your DataFactory it'll automatically include them.

How to forward to another object when using .NET Moq?

Given an object, I would like to create a mock that implements the interface of the object and mocks one method, but forwards the rest of the methods to the real object, not the base class.
For example:
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
mock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...)
// Here I would like to delegate the rest of the methods to the real sqlUtil object. How ?
So, in the example I want to mock just ISqlUtil.SpecialMethodToBeMocked and forward the rest of methods/properties to the existing instance sqlUtil.
Is it possible in Moq.NET ?
EDIT 1
It should work for generic methods as well.
You can't do this with Moq out of the box. However, I think you can achieve basically what you want if you go down to the next layer and use Castle DynamicProxy directly (which is what's underneath Moq).
So, given the following base code to simulate your issue (essentially, an interface, a concrete implementation and a factory because the concrete is hard to make/setup):
public interface ISqlUtil {
T SomeGenericMethod<T>(T args);
int SomeMethodToIntercept();
}
public class ConcreteSqlUtil : ISqlUtil {
public T SomeGenericMethod<T>(T args){
return args;
}
public int SomeMethodToIntercept() {
return 42;
}
}
public class SqlUtilFactory {
public static ISqlUtil CreateSqlUtil() {
var rVal = new ConcreteSqlUtil();
// Some Complex setup
return rVal;
}
}
You can then have the following test:
public void TestCanInterceptMethods() {
// Create a concrete instance, using the factory
var coreInstance = SqlUtilFactory.CreateSqlUtil();
// Test that the concrete instance works
Assert.AreEqual(42, coreInstance.SomeMethodToIntercept());
Assert.AreEqual(40, coreInstance.SomeGenericMethod(40));
// Create a proxy generator (you'll probably want to put this
// somewhere static so that it's caching works if you use it)
var generator = new Castle.DynamicProxy.ProxyGenerator();
// Use the proxy to generate a new class that implements ISqlUtil
// Note the concrete instance is passed into the construction
// As is an instance of MethodInterceptor (see below)
var proxy = generator.CreateInterfaceProxyWithTarget<ISqlUtil>(coreInstance,
new MethodInterceptor<int>("SomeMethodToIntercept", 33));
// Check that calling via the proxy still delegates to existing
// generic method
Assert.AreEqual(45, proxy.SomeGenericMethod(45));
// Check that calling via the proxy returns the result we've specified
// for our intercepted method
Assert.AreEqual(33, proxy.SomeMethodToIntercept());
}
The method interceptor looks like this:
public class MethodInterceptor<T> : Castle.DynamicProxy.IInterceptor {
private T _returns;
private string _methodName;
public MethodInterceptor(string methodName, T returns) {
_returns = returns;
_methodName = methodName;
}
public void Intercept(IInvocation invocation) {
if (invocation.Method.Name == _methodName) {
invocation.ReturnValue = _returns;
}
else {
invocation.Proceed();
}
}
}
Essentially, the interceptor checks if the method being called matches the one you're interested in and if so, returns the stored return value. Otherwise, it calls Proceed, which delegates the method call onto the concrete object supplied when the proxy was created.
The example code uses strings rather than lambdas to specify the method to intercept, obviously this could be changed (exercise for the reader). Also, this isn't using Moq, so you lose the Setup, Returns and Verify elements, which are replaced by the Interceptor, so this may be too far away from what you're after to be useful, however depending what your code really looks like it may be a viable alternative approach.
If you're unable to mock the class and delegate calls to the base by default, then you'll have to manually wire up the delegation to your separate instance.
var util = GetSqlUtil();
var mockUtil = new Mock<ISqlUtil>(MockBehavior.Strict);
mockUtil.Setup(x => x.SomeCall(...)).Returns<...>(args => util.SomeCall(args));
Having been successful with tricking Moq into creating a proxy for given class instance in my other SO answer here, I thought it would be easy to tweak the solution for your case of a given interface implementation.
No way
If you think of, it it makes sense: interface has no implementateion. And since Moq is aware mocked type is an interface - it does not even try to call the underlying proxy. That's it, end of story.
For those who don't give up easily
spoiler: still no luck
Looking at the library source code, I had a theory that it might be possible to force the correct execution path:
if (mock.TargetType.IsInterface) // !!! needs to be true here
{
// !!! we end up here and proceed to `DefaultValueProvider`
}
else
{
Debug.Assert(mock.TargetType.IsClass); // !!! needs to pass here
Debug.Assert(mock.ImplementsInterface(declaringType)); // !!! needs to pass here
// Case 2: Explicitly implemented interface method of a class proxy.
......
for that we could fulfill two conditions:
mock.TargetType should be a target class instance type
this.InheritedInterfaces should contain our interface
the second one is easy enough to build:
private void AddInheritedInterfaces(T targetInstance)
{
var moqAssembly = Assembly.Load(nameof(Moq));
var mockType = moqAssembly.GetType("Moq.Mock`1");
var concreteType = mockType.MakeGenericType(typeof(T));
var fi = concreteType.GetField("inheritedInterfaces", BindingFlags.NonPublic | BindingFlags.Static);
var t = targetInstance.GetType()
.GetInterfaces()
.ToArray();
fi.SetValue(null, t);
}
but as far as I'm aware, overriding an expression-bodied property marked internal (which Mock<>.TargetType is) is impossible without Reflection.Emit artillery, where it will likely become infeasible due to amonunt of overriding and subclassing required - you might be better off just forking Moq and patching the source code in this case (or submitting a PR maybe?).
What can be done
It should be possible to generate Setup LINQ expressions that automatically call through to your respective instance implementations:
//something along these lines, but this is basically sudocode
ISqlUtil sqlUtil = GetTheRealSqlUtilObjectSomehow(...);
var mock = new Mock<ISqlUtil>();
foreach(var methodInfo in typeof(ISqlUtil).GetMembers())
{ mock.Setup(Expression.Member(methodInfo)).Returns(Expression.Lambda(Expression.Call(methodInfo)).Compile()())
}
But given how much effort it is to account for everything properly, that again is probably not very feasible.
There is a workaround to do it, by using the method by #timur described in this answer.
While this method doesn't work directly on interfaces as described by his answer in the current thread, but it is indeed possible to do it via a generic factory method.
NOTE: The resulting Moq object will NOT be a true subclass rather it is a wrapped object and therefore only public virtual methods will be forwarded to the object (unlike a typical Moq which the base is automatically called for non public or non virtual methods/properties).
The factory mode would look like this:
static MyMock<T> CreateMock<T>(T target) where T : class, ISqlUtil
{
var superMock = new MyMock<T>(target); // now we can pass instances!
superMock.CallBase = true;
superMock.Setup(o => o.SpecialMethodToBeMocked(...)).Returns<...>(...);
return superMock;
}
And you use it like this:
var mockFunc = typeof(this).GetMethod("CreateMock").MakeGenericMethod(sqlUtil.GetType());
var superMock = mockFunc.Invoke(null, new object[] {sqlUtil}) as Mock;
While the implementation of MyMock will be based on the one described in this answer (but I am simplifying it a bit).
public class MyMock<T> : Mock<T>, IDisposable where T : class
{
public MyMock(T targetInstance)
{
var moqAssembly = typeof(Mock).Assembly;
var proxyFactoryType = moqAssembly.GetType("Moq.ProxyFactory");
var castleProxyFactoryInstance = proxyFactoryType.GetProperty("Instance").GetValue(null);
var castleProxyFactoryType = moqAssembly.GetType("Moq.CastleProxyFactory");
var generatorFieldInfo = castleProxyFactoryType.GetField("generator", BindingFlags.NonPublic | BindingFlags.Instance);
generatorFieldInfo.SetValue(castleProxyFactoryInstance, new MyProxyGenerator(targetInstance));
}
}
class MyProxyGenerator : ProxyGenerator
{
object _target;
public MyProxyGenerator(object target) {
_target = target;
}
// this method is 90% taken from the library source. I only had to tweak two lines (see below)
public override object CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, object[] constructorArguments, params IInterceptor[] interceptors)
{
if (_target is not null) return CreateClassProxyWithTarget(classToProxy, additionalInterfacesToProxy, _target, options, constructorArguments, interceptors);
return base.CreateClassProxy(classToProxy, additionalInterfacesToProxy, options, constructorArguments, interceptors);
}

How can I write this class to be fully generic and return different responses according to one request?

I was asked to create a series of reports for an application and as always, I'm looking for ways to reduce the amount of code written. I've started trying to come up with the easiest way to request a single report. Here's what I imagined:
var response = ReportGenerator.Generate(Reports.Report1);
//Reports would be an enum type with all of the available reports.
As soon as I tried to design that, the problems appeared. Every report has a different input and output. The input being the entity (or entities) on which the report is based and the output being the DTO holding the processed data.
Backing this up, I created this:
// The interface for every report
public interface IReport<INPUT, OUTPUT>
{
public OUTPUT GenerateReport(INPUT input);
}
// A base class for every report to share a few methods
public abstract class BaseReport<INPUT, OUTPUT> : IReport<INPUT, OUTPUT>
{
// The method required by the IReport interface
public OUTPUT GenerateReport(INPUT input)
{
return Process(input);
}
// An abstract method to be implemented by every concrete report
protected abstract OUTPUT Process(INPUT input);
}
public class ConcreteReport : BaseReport<SomeEntity, SomeDto>
{
protected override SomeDto Process(SomeEntity input)
{
return default(SomeDto);
}
}
At first I was considering to have every concrete report to specify the logic responsible to determine its own input. I quickly saw that it would make my class less testable. By having the report request an instance of the INPUT generic type I can mock that object and test the report.
So, what I need is some kind of class to tie a report (one of the enum values) to a concrete report class responsible for its generation. I'm trying to use an approach similar to a dependency injection container. This is the class I'm having trouble to write.
I'll write below what I have with comments explainning the problems I've found (it's not supposed to be syntatically correct - it's just a stub since my problem is exactly the implementation of this class):
public class ReportGenerator
{
// This would be the dictionary responsible for tying an enum value from the Report with one of the concrete reports.
// My first problem is that I need to make sure that the types associated with the enum values are instances of the BaseReport class.
private readonly Dictionary<Reports, ?> registeredReports;
public ReportGenerator()
{
// On the constructor the dictionary would be instantiated...
registeredReports = new Dictionary<Reports, ?>();
// and the types would be registered as if in a dependency injection container.
// Register(Reports.Report1, ConcreteReport);
// Register(Reports.Report2, ConcreteReport2);
}
// Below is the most basic version of the registration method I could come up with before arriving at the problems within the method GenerateReport.
// T repository - this would be the type of the class responsible for obtainning the input to generate the report
// Func<T, INPUT> expression - this would be the expression that should be used to obtain the input object
public void Register<T, INPUT>(Reports report, Type reportConcreteType, T repository, Func<T, INPUT> expression)
{
// This would basically add the data into the dictionary, but I'm not sure about the syntax
// because I'm not sure how to hold that information so that it can be used later to generate the report
// Also, I should point that I prefer to hold the types and not instances of the report and repository classes.
// My plan is to use reflection to instantiate them on demand.
}
// Based on the registration, I would then need a generic way to obtain a report.
// This would the method that I imagined at first to be called like this:
// var response = ReportGenerator.Generate(Reports.Report1);
public OUTPUT Generate(Reports report)
{
// This surely does not work. There is no way to have this method signature to request only the enum value
// and return a generic type. But how can I do it? How can I tie all these things and make it work?
}
}
I can see it is not tied with the report interface or abstract class but I can't figure out the implementation.
I am not sure that it is possible to achieve such behaviour with enum, so I can propose you the following solution:
Use some identifier generic class(interface) in place of enum values. To use it as key in dictionary you will also have to have some non-generic base for this class.
Have some static class with aforementioned identifier classes as specific static properties.
Use values from static class properties as keys in ReportGenerator class.
Here are required interfaces:
public interface IReportIdentifier
{
}
public interface IReportIdentifier<TInput, TOutput> : IReportIdentifier
{
}
public interface IReport<TInput, TOutput>
{
TOutput Generate(TInput input);
}
Here is the static "enum" class:
public static class Reports
{
public static IReportIdentifier<String, Int32> A
{
get { return null;}
}
public static IReportIdentifier<Object, Guid> B
{
get { return null; }
}
}
And here is the ReportGenerator class:
public class ReportGenerator
{
IDictionary<IReportIdentifier, Object> reportProducers = new Dictionary<IReportIdentifier, Object>();
public void Register<TInput, TOutput>(IReportIdentifier<TInput, TOutput> identifier, IReport<TInput, TOutput> reportProducer)
{
reportProducers.Add(identifier, reportProducer);
}
public TOutput Generate<TInput, TOutput>(IReportIdentifier<TInput, TOutput> identifier, TInput input)
{
// Safely cast because it is this class's invariant.
var producer = (IReport<TInput, TOutput>)reportProducers[identifier];
return producer.Generate(input);
}
}
As you see, we use cast but it is hidden inside the Generate method and if our Register method is the only access point to the reportProducers dictionary this cast will not fail.
And also as #CoderDennis pointed:
Then you could always use T4 to generate that static class and its
static properties and could even create an extension method that
returns the proper IReportIdentifier from your enum.
It seems to me that you may want to rethink the design.
You essentially have methods that take objects in and spit objects out. Granted, you use generics, but that doesn't mean much since there are no constraints on input/output and thus no way to commonly process them in calling code.
In fact, I think the use of generics is potentially a hindrance with the given approach, because passing in the wrong combination of generic types will result in a error, and it's not clear to the caller what is valid and what is not.
Given the approach, it's unclear what benefit all of the extra classes give over non-abstractions like:
int r1Output = Report1StaticClass.GetOutput(string input);
string r2Output = Report2StaticClass.GetOtherOutput(int input);
double r3Output = Report3StaticClass.GetWhatever(double input);
A different approach might be to encapsulate input/output something similar to this, but adjusted to your needs. This isn't meant to be an exact approach, but just something to demonstrate what I'm suggesting. Also, I haven't actually tested/compile this. Consider it pseudo-code:
//something generic that can be easily mocked and processed in a generic way
//your implementation almost certainly won't look exactly like this...
//but the point is that you should look for a common pattern with the input
interface IInput
{
ReportTypeEnum EntityType{ get; set; }
int EntityId{ get; set; }
}
interface IReportTemplate
{
//return something that can be bound to/handled generically.
//for instance, a DataSet can be easily and dynamically bound to grid controls.
//I'm not necessarily advocating for DataSet, just saying it's generic
//NOTE: the guts of this can use a dynamically assigned
// data source for unit testing
DataSet GetData(int entityId);
}
//maybe associate report types with the enum something like this.
[AttributeUsage (AttributeTargets.Field, AllowMultiple = false)]
class ReportTypeAttribute : Attribute
{
public Type ReportType{ get; set; }
//maybe throw an exception if it's not an IReportTemplate
public ReportTypeAttribute(Type reportType){ ReportType = reportType; }
}
//it should be easy for devs to recognize that if they add an enum value,
//they also need to assign a ReportType, thus your code is less likely to
//break vs. having a disconnect between enum and the place where an associated
//concrete type is assigned to each value
enum ReportTypeEnum
{
[ReportType(typeof(ConcreteReportTemplate1))]
ReportType1,
[ReportType(typeof(ConcreteReportTemplate2))]
ReportType2
}
static class ReportUtility
{
public static DataSet GetReportData(IInput input)
{
var report = GetReportTemplate(input.EntityType);
return report.GetData(input.EntityId);
}
private static IReportTemplate GetReportTemplate(ReportTypeEnum entityType)
{
//spin up report by reflecting on ReportTypeEnum and
//figuring out which concrete class to instantiate
//based on the associated ReportTypeAttribute
}
}

How can I guarantee that an interface and a class method parameters match without manually checking?

I recently noticed a bug due to a mismatched parameter order in the class to its interface parameter order. I felt that this should have been a compile error. I found out that Interfaces do not constrain the parameter names. So if you see my example below I have firstParameter and secondParameter reversed, I also have parameterOne and parameterTwo, both as valid builds. This may build just fine, but you will likely run into runtime errors.
On the other hand, it does require the order of the types of the parameters to match. So I thought perhaps I do not need to place the parameter names in the interface and just the value types, but that does not work and the interface would still need to provide a description of what the types are in terms of what a consumer would place there.
My Question
Is there a way to guarantee at build time that a class matches the interface parameter names? I would prefer not to do this manually.
The reason this is important is even though the method variables cannot be setup to be used by the interface, someone consuming a service reference or other use of an interface would see the Interface parameters at the time of setup and that is the expected use of the parameters. If I cannot rely on a contract to be exact, what is the point of a contract in the first place?
interface IParameterTest
{
void TwoStringParameters(string firstParameter, string secondParameter);
void TwoStringParametersAndAnInt(string firstParameter, string secondParameter, int thirdParameter);
}
public class ParameterTest : IParameterTest
{
//Builds and matches interface
//public void TwoStringParameters(string firstParameter, string secondParameter)
//{
// throw new NotImplementedException();
//}
//Builds and does not match interface
//public void TwoStringParameters(string secondParameter, string firstParameter)
//{
// throw new NotImplementedException();
//}
//Builds and does not match interface
public void TwoStringParameters(string parameterOne, string parameterTwo)
{
throw new NotImplementedException();
}
//Builds and matches interface
public void TwoStringParametersAndAnInt(string firstParameter, string secondParameter, int thirdParameter)
{
throw new NotImplementedException();
}
//Does not build or match interface
//public void TwoStringParametersAndAnInt(int firstParameter, string secondParameter, string thirdParameter)
//{
// throw new NotImplementedException();
//}
}
Is there a way to guarantee at build time that a class matches the interface parameter names? I would prefer not to do this manually.
Not within the C# language. However:
You could write a unit test to check, reasonably easily. Not quite build time, but still early enough to catch errors before they're big problems.
You could write a Roslyn code diagnostic to flag it as an error (and even provide a code fix for it).
Of course, the unit test could be written via Roslyn as well, but you could do it fairly easily just using plain reflection.
It's not entirely clear from your question whether you've spotted the really nasty problem with parameter names being wrong, by the way - it's not just in terms of human readability, but it can significantly affect behaviour if you use named arguments. For example, suppose you have code like this:
public interface IFoo
{
void Foo(int x, int y);
}
public class FooImpl : IFoo
{
public void Foo(int y, int x) { ... }
}
...
IFoo foo = new FooImpl();
foo.Foo(x: 10, y: 20); // Equivalent to foo.Foo(10, 20)
Now if someone decides to use var instead, the compile-time type of foo is changed, so suddenly the named arguments map to different parameters.
var foo = new FooImpl();
foo.Foo(x: 10, y: 20); // Equivalent to foo.Foo(20, 10)
Perfectly valid code... but with a different meaning to the previous code. There are other times that changing the compile-time type of a variable can affect things, but that's usually around overloading etc... this is in the simple case where there really is just one method.
As Jon says, C# doesn't really care what the parameters are called, but if you wanted to reflectively assert the parameter names for yourself; either at start up or in a unit test, you could use something like this:
public class Program
{
public static void Main(string[] args)
{
var assembly = Assembly.GetAssembly(typeof(Program));
var types = assembly
.GetTypes()
.Where(x => x.IsClass && x.GetInterfaces().Any());
foreach (var type in types)
{
var interfaces = type.GetInterfaces().Where(x => x.Assembly == assembly);
foreach (var iface in interfaces)
{
var classMethods = type.GetMethods();
foreach (var interfaceMethod in iface.GetMethods())
{
var classMethod = classMethods.First(x => x.ToString() == interfaceMethod.ToString());
Debug.Assert(
interfaceMethod.GetParameters().Select(x => x.Name).SequenceEqual(classMethod.GetParameters().Select(x => x.Name)),
"Incorrect parameter names in method: " + type.Name + "." + classMethod.Name);
}
}
}
}
public interface ITest
{
void MethodA(string first, string second);
}
public class TestA : ITest
{
public void MethodA(string first, string second) { }
}
public class TestB : ITest
{
public void MethodA(string second, string first) { }
}
}
FxCop already has a rule to enforce this. You can enable code analysis to run on build in your project properties, then configure the code analysis rule set to treat that warning as an error. If you integrate that into your build process you will force all your developers to address that issue before their builds will succeed.
Yes, you have a few build-time alternatives. You'd have to weigh whether they are worth the effort.
create a custom static code analysis rule (what used to be FxCop)
use Roslyn and plug it into MSBuild
something completely custom plugged into MSBuild that fails the build if you don't have a match
Your question
If I cannot rely on a contract to be exact, what is the point of a contract in the first place?
is worth considering, however names of required parameters as contractual requirement may be considered quite narrow. There is a compile-time way to fix this, and you've even suggested it in your question: you are bound by the order, number and type of parameters. If you needed a very strict interface, you could abstract the parameters by wrapping the simple types, preventing a case such as accidental argument swapping.
Again, you'd have to weigh whether it's worth it. You're buying interface safety at the cost of more code and cognitive load.
In this case I would suggest a much better solution is to refactor the interface to use the parameter object design pattern rather than messing around with enforcing the parameter names of two strings are implemented in the correct order.
Example if string 1 was "firstName" and string 2 was "lastName" you are much better off with a class with two properties FirstName and SecondName and then have your interface depend on this parameter object rather than low level data types such as strings.

Categories

Resources