Swapping between versions of a webservice c# - c#

I wish to maintain code that calls an existing webservice but make it so I can call a newer version of the same webservice (based on a config setting). I'll need to have different namespaces as the webservice is the same name. Does anyone have any best practice patters for accomplishing this?
Thanks,
Steven

The "Factory" pattern (and probably "Facade" pattern) are your friends here.
So, given you have two services that implement a common method or set of methods you can do this kind of thing to make a general service factory:
I'm assuming you have two services called ServiceOld and ServiceNew (they could have the same name and sit in different namespaces as is your case). And that these services share a common method public string GetName();.
First I create an interface that embodies these services:
public interface IService
{
string GetName();
}
Now, if you can modify the service code directly you could implement this interface directly on your services, or you could perhaps inherit down your services and implement this interface. I'm going to assume that your services are both not under your control and are sealed. So I would implement two wrapper (or facade) classes.
public class ServiceOldWrapper : IService
{
private ServiceOld _inner = new ServiceOld();
public string GetName()
{
return _inner.GetName();
}
}
public class ServiceNewWrapper : IService
{
private ServiceNew _inner = new ServiceNew();
public string GetName()
{
return _inner.GetName();
}
}
Now I can write the factory class.
public class ServiceFactory
{
public IService CreateService()
{
if (configValueThatYouNeedToRead == "Old")
{
return new ServiceOldWrapper();
}
else
{
return new ServiceNewWrapper();
}
}
}
Now calling this becomes simple:
var sf = new ServiceFactory();
var s = sf.CreateService();
var name = s.GetName();
You probably will need to handle cleaning up your services a little better than I have so your code will be a bit more complicated, but this should get you started.

Related

Isolating Service Fabric ServiceContext for unit testing

I have a method in my Service fabric Stateless service application which get the configuration stored in Settings.xml from ServiceContext
public static string GetConnectionString()
{
if (context == null)
return string.Empty;
// return context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings.Sections["MySection"].Parameters["ConnectionString"].Value;
ICodePackageActivationContext activationContext = context.CodePackageActivationContext;
ConfigurationPackage configPackage = activationContext.GetConfigurationPackageObject("Config");
ConfigurationSettings configSettings = configPackage.Settings;
string connectionString = configSettings.Sections["ConnectionData"].Parameters["ConnectionString"].Value;
return connectionString;
}
In the above code I split the code into many lines for easier understanding, actually i use the commented code in my application.
I need to write unit test for this method.
I could mock ServiceContext and ICodeActivationContext
But i could not create objects for ConfigurationSettings and ConfigurationPackage since they have internal constructors.
How do I isolate these classes in my unit test. Or should i exclude the service context part from my unit test.
Now you can use a NuGet package named ServiceFabric.Mocks, which offers mocks for most Service Fabric classes.
For example, you can use MockStatelessServiceContextFactory.Default to get a StatelessServiceContext mock.
I would create an interface that returns parameters from service fabric (one of them is the connection string). Then a class that implements the interface the way you wrote in the question. And that interface can be mocked used in unittesting.
The result is - that you cannot test the method that actually read from service parameters, but at least you can test everyone who uses it without the need to mock ServiceContext and alike.
I had an almost identical issue with the System.Printing PrintSystemJobInfo class, it has a sealed constructor so it proved very difficult to mock. I assume you are creating an interface that closely resembles the class you wish to mock, then creating a wrapper for the actual class that implements the interface.
A solution to your problem is to pass the parent class as a parameter in the constructor of the child class (so the child class has access to the parent methods and can build the real implementation that you intend to wrap).
The following code demonstrates how I did it with PrintSystemJobInfo;
using System;
using System.Printing;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
var server = new LocalPrintServer();
IPrintQueue testablePrintQueue = new RealPrintQueue(server);
IPrintSystemJobInfo printSystemJobInfo = testablePrintQueue.AddJob();
var result = printSystemJobInfo.IsBlocked;
Console.WriteLine(result);
}
public interface IPrintSystemJobInfo
{
bool IsBlocked { get; }
}
public interface IPrintQueue
{
IPrintSystemJobInfo AddJob();
}
public class RealPrintQueue:IPrintQueue
{
private PrintQueue _queue;
public RealPrintQueue(LocalPrintServer server)
{
_queue = server.DefaultPrintQueue;
}
public IPrintSystemJobInfo AddJob()
{
return new RealPrintSystemJobInfo(_queue);
}
}
public class RealPrintSystemJobInfo: IPrintSystemJobInfo
{
private PrintSystemJobInfo job;
public RealPrintSystemJobInfo(PrintQueue queue)
{
job = queue.AddJob();
}
public bool IsBlocked
{
get { return job.IsBlocked; }
}
}
}
}
I have tried to keep this as simple as possible so I have only wrapped IsBlocked property, but you could extend it to what ever you liked (obviously).

Universally accessible class/object with constructor parameters

I'm creating a platform/foundation component (set of .NET assemblies) that is going to be responsible for accessing (reading/writing) configuration values. This component is to be used by other components that are going to be created on the platform.
I want this component to be easy to use for consumers, but also have high testability and maintainability. In my current design I have a static class (ConfigurationManager) that contains some methods (for example GetKeyValueSetting). This ConfigurationManager class is special in that it can either get the configuration values from the local .NET .config file, but also from a SharePoint list (some of the components are hosted in a Shared SharePoint environment) and even from another shared config value store. The Manager should be able to read from multiple locations in a prioritized fashion:
if running on SharePoint: 1. SharePointSettingsProvider, 2. SharedStoreSettingsProvider
if not running on SharePoint: 1. ConfigFileSettingsProvider 2. SharedStoreSettingsProvider
I know that a static class creates a lot of issues in regards to testability, extensibility etc so I don't want to use that. My next alternative is a Singleton, but in regards to the aforementioned -ilities this is not a much better solution. Any ideas for a better solution?
My current design is as follows:
public static class ConfigurationManager
{
// internal for testability
internal IEnumerable<ISettingsProvider> SettingsProviders {get;set;}
// internal for testability
internal ISettingsProviderFactory ProvidersFactory {get;set;}
public static string GetKeyValueSetting(string key)
{
}
}
public interface ISettingsProvider
{
string GetKeyValueSetting(string key);
}
public class ConfigFileSettingsProvider : ISettingsProvider
{
}
public class SharePointSettingsProvider : ISettingsProvider
{
}
public class SharedStoreSettingsProvider : ISettingsProvider
{
}
public interface ISettingsProviderFactory
{
IEnumerable<ISettingsProvider> GetProviders();
}
Why not this:
public abstract class ConfigurationManager
{
public abstract string GetKeyValueSetting(string key);
public static ConfigurationManager GetInstance()
{
return GetInstance(GetDefaultSettingProvider(), GetDefaultProviderFactory());
}
public static ConfigurationManager GetInstance(ISettingsProvider provider, IProviderFactory factory)
{
return new InternallyVisibleConfigurationManagerImplementation(provider, factory);
}
}
This has a lot of benefits:
ConfigurationManager is abstract, so calling code can Mock it easily
It's easy to get a default implementation
Calling assemblies can easily configure it with different providers and factories
Calling assemblies cannot couple to a concrete type
You can change the specific implementation type easily (i.e., maybe you want a caching proxy so you don't need to make expensive calls to sharepoint as often)
You keep all your easy testability
You can refactor to a singleton or other variations of life-cycle management without changing client code
If callers really hate this, and don't mind their unit tests calling sharepoint sites sometimes, you could add a convenience method like this:
public static string GetKeyValueSetting(string key)
{
return GetInstance().GetKeyValueSetting(key);
}
EDIT
To use a couple of stores, create a class like this:
internal class OrderedCompositeSettingProvider : ISettingProvider
{
private readonly ISettingProvider[] _providers;
private OrderedCompositeSettingProvider(ISettingProvider[] providers)
{
_providers = providers;
}
internal static ISettingProvider GetInstance(params ISettingProvider[] providers)
{
return new OrderedCompositeSettingProvider(providers)
}
public string GetKeyValueSetting(string key)
{
foreach(var provider in _providers)
{
var setting = provider.GetKeyValueSetting(key);
if(!string.IsNullOrEmpty(setting)) return setting;
}
return string.empty;
}
}
Then in the ConfigurationManager factory method:
public static ConfigurationManager GetInstance()
{
return GetInstance(GetAppropriateProvider(), GetDefaultProviderFactory());
}
private static ISettingsProvider GetAppropriateProvider()
{
if(ShouldUseSharepoint())
return OrderedCompositeSettingProvider.GetInstance(new SharepointProvider(), new StoredSettingsProvider());
return OrderedCompositeSettingProvider.GetInstance(new ConfigFileProvider(), new StoredSettingsProvider());
}

Build a class that can be tested

i have a class that uses a proxy class inside to call a service that provide data. of course if the method create the proxy inside there is a problem to test that class. do you think that the proxy should be given in the constructor even if it can be created inside without "knowing" ?
You should provide class dependencies to class via dependency injection (constructor, property, parameter). That makes your class testable and allows to mock all those dependencies.
UPDATE:
Inject service proxy:
class Foo
{
private IServiceProxy _serviceProxy;
public Foo(IServiceProxy _serviceProxy)
{
_serviceProxy = serviceProxy;
}
public void Bar()
{
var staff = _serviceProxy.GetStaff();
}
}
Btw consider to hide information about proxy from your class. E.g. implement by proxy same interface that actual service has and provide IService to your class.
UPDATE2 (gateway):
All our domain needs - to get some staff. So, we define interface:
interface IStaffService
{
Staff GetStaff();
}
Our domain class (your tested class uses only this interface and does not depend on web services, proxy creation and other infrastructure concerns).
Next create Gateway (see definition on Martin Fowler site) for your service:
public MyServiceProxyGateway : IStaffService
{
public Staff GetStaff()
{
var proxy = new YourProxyType();
proxy.X = value;
proxy.Y = value;
var response = proxy.CallActualServiceMethod();
Staff staff = new Staff();
staff.Value = response.Something;
return staff;
}
}
Your code now completely unaware about all this infrastructure communications. And you use handy interface GetStaff instead of CallActualServiceMethod.
Well, there's a difference between "the proxy class knows how to instantiate itself" and "the class knows how to instantiate the proxy class". The second makes unit testing alot harder(if not impossible) if you pack that knowledge inside.
I'd use dependency injection (either via a framework,constructor or property) to take that knowledge to the caller - and make it testable.
To test my proxy classes i normally give the target that should be proxied within the constructor. Thous giving me the possibility to give a stub object for testing.
public class MyProxy : IProxiedInterface
{
private IProxiedInterface _Target;
public MyProxy(IProxiedInterface target)
{
if(target == null)
throw new ArgumentNullException("target");
_Target = target;
}
// ToDo: Implement all functions from IProxiedInterface
// and delegate them to the target
public bool DoSomething()
{
return _Target.DoSomething();
}
}

should new behavior be introduced via composition or some other means?

I chose to expose some new behavior using composition vs. injecting a new object into my consumers code OR making the consumer provide their own implementation of this new behavior. Did I make a bad design decision?
I had new requirements that said that I needed to implement some special behavior in only certain circumstances. I chose to define a new interface, implement the new interface in a concrete class that was solely responsible for carrying out the behavior. Finally, in the concrete class that the consumer has a reference to, I implemented the new interface and delegate down to the class that does the work.
Here are the assumptions that I was working with...
I haven an interface, named IFileManager that allows implementors to manage various types of files
I have a factory that returns a concrete implementation of IFileManager
I have 3 implementations of IFileManager, these are (LocalFileManager, DfsFileManager, CloudFileManager)
I have a new requirements that says that I need to manage permissions for only the files being managed by the CloudFileManager, so the behavior for managing permissions is unique to the CloudFileManager
Here is the test that led me to the code that I wrote...
[TestFixture]
public class UserFilesRepositoryTest
{
public interface ITestDouble : IFileManager, IAclManager { }
[Test]
public void CreateResume_AddsPermission()
{
factory.Stub(it => it.GetManager("cloudManager")).Return(testDouble);
repository.CreateResume();
testDouble.AssertWasCalled(it => it.AddPermission());
}
[SetUp]
public void Setup()
{
testDouble = MockRepository.GenerateStub<ITestDouble>();
factory = MockRepository.GenerateStub<IFileManagerFactory>();
repository = new UserFileRepository(factory);
}
private IFileManagerFactory factory;
private UserFileRepository repository;
private ITestDouble testDouble;
}
Here is the shell of my design (this is just the basic outline not the whole shibang)...
public class UserFileRepository
{
// this is the consumer of my code...
public void CreateResume()
{
var fileManager = factory.GetManager("cloudManager");
fileManager.AddFile();
// some would argue that I should inject a concrete implementation
// of IAclManager into the repository, I am not sure that I agree...
var permissionManager = fileManager as IAclManager;
if (permissionManager != null)
permissionManager.AddPermission();
else
throw new InvalidOperationException();
}
public UserFileRepository(IFileManagerFactory factory)
{
this.factory = factory;
}
private IFileManagerFactory factory;
}
public interface IFileManagerFactory
{
IFileManager GetManager(string managerName);
}
public class FileManagerFactory : IFileManagerFactory
{
public IFileManager GetManager(string managerName)
{
IFileManager fileManager = null;
switch (managerName) {
case "cloudManager":
fileManager = new CloudFileManager();
break;
// other managers would be created here...
}
return fileManager;
}
}
public interface IFileManager
{
void AddFile();
void DeleteFile();
}
public interface IAclManager
{
void AddPermission();
void RemovePermission();
}
/// <summary>
/// this class has "special" behavior
/// </summary>
public class CloudFileManager : IFileManager, IAclManager
{
public void AddFile() {
// implementation elided...
}
public void DeleteFile(){
// implementation elided...
}
public void AddPermission(){
// delegates to the real implementation
aclManager.AddPermission();
}
public void RemovePermission() {
// delegates to the real implementation
aclManager.RemovePermission();
}
public CloudFileManager(){
aclManager = new CloudAclManager();
}
private IAclManager aclManager;
}
public class LocalFileManager : IFileManager
{
public void AddFile() { }
public void DeleteFile() { }
}
public class DfsFileManager : IFileManager
{
public void AddFile() { }
public void DeleteFile() { }
}
/// <summary>
/// this class exists to manage permissions
/// for files in the cloud...
/// </summary>
public class CloudAclManager : IAclManager
{
public void AddPermission() {
// real implementation elided...
}
public void RemovePermission() {
// real implementation elided...
}
}
Your approach to add your new behavior only saved you an initialization in the grand scheme of things because you to implemented CloudAclManager as separate from CloudFileManager anyways. I disagree with some things with how this integrates with your existing design (which isn't bad)...
What's Wrong With This?
You separated your file managers and made use of IFileManager, but you didn't do the same with IAclManager. While you have a factory to create various file managers, you automatically made CloudAclManager the IAclManager of CloudFileManager. So then, what's the point of having IAclManager?
To make matters worse, you
initialize a new CloudAclManager
inside of CloudFileManager every time you try to get its ACL
manager - you just gave factory
responsibilities to your
CloudFileManager.
You have CloudFileManager implement IAclManager on top of having it as a property. You just moved the rule that permissions are unique to CloudFileManager into your model layer rather than your business rule layer. This also results in supporting the unnecessary
potential of circular referencing between self and property.
Even if you wanted
CloudFileManager to delegate the
permission functionality to
CloudAclManager, why mislead other
classes into thinking that
CloudFileManager handles its own
permission sets? You just made your
model class look like a facade.
Ok, So What Should I Do Instead?
First, you named your class CloudFileManager, and rightly so because its only responsibility is to manage files for a cloud. Now that permission sets must also be managed for a cloud, is it really right for a CloudFileManager to take on these new responsibilities? The answer is no.
This is not to say that you can't have code to manage files and code to manage permissions in the same class. However, it would then make more sense for the class to be named something more general like CloudFileSystemManager as its responsibilities would not be limited to just files or permissions.
Unfortunately, if you rename your class it would have a negative effect on those currently using your class. So how about still using composition, but not changing CloudFileManager?
My suggestion would be to do the following:
1. Keep your IAclManager and create IFileSystemManager
public interface IFileSystemManager {
public IAclManager AclManager { get; }
public IFileManager FileManager { get; }
}
or
public interface IFileSystemManager : IAclManager, IFileManager {
}
2. Create CloudFileSystemManager
public class CloudFileSystemManager : IFileSystemManager {
// implement IFileSystemManager
//
// How each manager is set is up to you (i.e IoC, DI, simple setters,
// constructor parameter, etc.).
//
// Either way you can just delegate to the actual IAclManager/IFileManager
// implementations.
}
Why?
This will allow you to use your new behavior with minimal impact to your current code base / functionality without affecting those who are using your original code. File management and permission management can also coincide (i.e. check permissions before attempting an actual file action). It's also extensible if you need any other permission set manager or any other type of managers for that matter.
EDIT - Including asker's clarification questions
If I create IFileSystemManager : IFileManager, IAclManager, would the repository still use the FileManagerFactory and return an instance of CloudFileSystemManager?
No, a FileManagerFactory should not return a FileSystemManager. Your shell would have to update to use the new interfaces/classes. Perhaps something like the following:
private IAclManagerFactory m_aclMgrFactory;
private IFileManagerFactory m_fileMgrFactory;
public UserFileRepository(IAclManagerFactory aclMgrFactory, IFileManagerFactory fileMgrFactory) {
this.m_aclMgrFactory = aclMgrFactory;
this.m_fileMgrFactory = fileMgrFactory;
}
public void CreateResume() {
// I understand that the determination of "cloudManager"
// is non-trivial, but that part doesn't change. For
// your example, say environment = "cloudManager"
var environment = GetEnvMgr( ... );
var fileManager = m_fileMgrFactory.GetManager(environment);
fileManager.AddFile();
// do permission stuff - see below
}
As for invoking permission stuff to be done, you have a couple options:
// can use another way of determining that a "cloud" environment
// requires permission stuff to be done
if(environment == "cloudManager") {
var permissionManager = m_aclMgrFactory.GetManager(environment);
permissionManager.AddPermission();
}
or
// assumes that if no factory exists for the environment that
// no permission stuff needs to be done
var permissionManager = m_aclMgrFactory.GetManager(environment);
if (permissionManager != null) {
permissionManager.AddPermission();
}
I think that composition is exactly the right means to to this kind of trick. But I think you should keep it more simple (KISS) and just make an IAclManager property in the IFileManager and set it to null by default and set the SecurityManager implementation for the cloud service there.
This has different upsides:
You can check if permissions need to be checked by nullchecking the securityManager property. This way, if there doesn't need to be permissionsManaging done (as with localfile system), you don't have exceptions popping up. Like this:
if (fileManager.permissionsManager != null)
fileManager.permissionsManager.addPermission();
When you then carry out the task (to add or delete a file), you can check again if there's a permissionsManager and if the permission is given, if not throw exception (as you'll want to throw the exception when a permission to do an action is missing, not if a permission is missing in general if you're not going to add or delete files).
You can later on implement more IAclManagers for the other IFileManagers when your customer changes the requirements next time the same way as you would now.
Oh, and then you won't have such a confusing hierarchy when somebody else looks at the code ;-)
In general it looks good, but I do have a few suggestions. It seems that your CreateResume() method implementation demands a IFileManager that is also an IAclManager (or else it throws an exception).
If that is the case, you may want to consider adding an overload to your GetManager() method in which you can specify the interface that you require, and the factory can have the code that throws an exception if it doesn't find the right file manager. To accompolish this you can add another interface that is empty but implements both IAclManager and IFileManager:
public interface IAclFileManager : IFileManager, IAclManager {}
And then add the following method to the factory:
public T GetManager<T>(string name){ /* implementation */}
GetManager will throw an exception if the manager with the name given doesn't implement T (you can also check if it derives from or is of type T also).
All that being said, if AddPermissions doesn't take any parameters (not sure if you just did this for the post), why not just call AddPermissions() from CloudFileManager.AddFile() method and have it completely encapsulated from the user (removing the need for the new IAclManager interface)?
In any event, doesn't seem like a good idea to call AddFile in the CreateResume() method and only then throw the exception (since you now you have now created a file without the correct permissions which could be a security issue and also the consumer got an exception so he may assume that AddFile didn't succeed, as opposed to AddPermission).
Good luck!

Question about Factory Design Architecture

Consider this example
The Interface
interface IBusinessRules
{
string Perform();
}
The Inheritors
class Client1BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 1 Performed";
}
}
class Client2BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 2 Performed";
}
}
class Client3BusinessRules: IBusinessRules
{
public string Perform()
{
return "Business rule for Client 3 Performed";
}
}
The factory class
class BusinessRulesFactory
{
public IBusinessRules GetObject(int clientIdentityCode)
{
IBusinessRules objbase = null;
switch (clientIdentityCode)
{
case 1:
objbase = new Client1BusinessRules();
break;
case 2:
objbase = new Client2BusinessRules();
break;
case 3:
objbase = new Client3BusinessRules();
break;
default:
throw new Exception("Unknown Object");
}
return objbase;
}
}
sample usage:
class Program
{
static void Main(string[] args)
{
BusinessRulesFactory objfactory = new BusinessRulesFactory ();
IBusinessRulesFactory objBase = objfactory.GetObject(2);
Console.WriteLine(objBase.Perform());
objBase = objfactory.GetObject(3);
Console.WriteLine(objBase.Perform());
Console.Read();
}
}
My question is, how about I add another method on the ALgorithm1 Class
but not in the interface because im going to just use it on special scenario?
class Client1BusinessRules: IBusinessRules
{
public string Perform()
{
return "Client1 Business rules is Performed";
}
public string Calculate()
{
return "Additional functionality for CLient1";
}
}
how Am I suppose to call that on the UI something like this
objBase = objfactory.GetObject(1);
Console.WriteLine(objBase.Calculate());
Is there any other solution? thanks in advance
EDIT: I rewrite it to resemble my current project design
I presume you are using the factory class in order to:
have a standard facade accepting parameters that lead to business rule selection and provisioning
encapsulate business rule provisioning
decouple the users from actual implementations of IBusinessRules
Hence I would solve your problem by introducing new interface
interface IComputableRules : IBusinessRules
{
string Calculate();
}
As long as you follow the interface-based design, there's nothing wrong about casting the actual instance to an interface different from IBusinessRules.
IBusinessRules businessRule = objFactory.GetObject(...some input...)
...
// check if the computable service is supported and print the result
IComputableRules computable = businessRule as IComputableRules;
if (computable)
{
Console.WriteLine(computable.Calculate());
}
Here you can think of you business rule classes as service providers, that guarantee some basic service, plus optional additional services depending on the nature of the business rule.
Note: By turning the BusinessRulesFactory into a generic class you might make the indication of a specific service a part of the factory contract, and make sure the returned business rule implementation will support a particular (otherwise optional) service.
class BusinessRulesFactory<TService> where TService : IBusinessRules
{
public TService GetObject(int clientIdentityCode)
{
// ... choose business rule in respect to both clientIdentityCode and TService
}
}
In case where you wouldn't require a specific additional service to be available, you'd just use IBusinessRules as the actual type parameter.
The whole point of the factory pattern is to return the proper implementation of a contract so that the consumer shouldn't worry about how to instantiate it but simply invoke its methods. You could always test the actual type, cast to it and invoke the method but that's a very bad design and I wouldn't recommend it. The consumer shouldn't know anything about the actual type. You will need to rethink your design.
If you want to stick to the current architecture you can introduce a new interface declaration
interface ICalculationRules
{
string Calculate();
}
Now let modify Client1BusinessRules by adding the interface declaration:
class Client1BusinessRules: IBusinessRules, ICalculationRules
{
// everything remains the same
}
Modify your calling code like this:
var objBase = objfactory.GetObject(1);
Console.WriteLine(objBase.Calculate());
var calcBase = obj as ICalculationRules;
if (calcBase != null) calculable.Calculate();
Maintenance implication: Every time you introduce a new interface, you have to touch all your calling code. Since you posted that this code is placed in the UI code, this can get quite a mess.
Each interface you are introducing just means added behaviour to a class. If you have a large range of different behaviours, then the solution above my not feel right, because there is always the need to use the as operation and conditional execution a method. If you want to stick to some classic design pattern this variability of behaviour can be countered with the Decorator Pattern or the Strategy Pattern. They can be smoothly combined with the Factory Pattern.
There are many approaches that can be employed in this case, and it depends on the cost you're willing to put in order to get the value.
For example, you can go with simple casting. You'll get the algorithm object from the factory, cast it to the proper (specific) algorithm object, and then call the "Calculate" function.
Another option - a much more generic one, that would also require much more code - would be to supply a querying mechanism within the base class, that will supply information about the available functionality within the object. This is somewhat comparable to querying for interfaces in COM.
The important questions you need to ask yourself is:
1. How many times will you need to implement specific functionality?
2. Is there a way you can solve the problem with added polymorphism stemming from the base class?
3. Will users of the derived objects know that they are using the specific object, or do you want them to be ignorant of the actual type?
In general what I personally do in such cases is start with the simplest solution (in this case, specific casting and calling the function), and go back and refactor as I go, when I have some more data about the domain. If you're sensitive to "smelly code", you'll get to a point where you see there's too much clutter and you'll refactor it into a better solution.
I would modify it like this
interface IBusinessRules
{
string Perform();
bool CanCalculate { get; }
string Calculate();
}
and add an abstract base class (optional but recommended for further extensibility)
public abstract class BusinessRules : IBusinessRules {
protected BusinessRules() {
}
protected virtual bool CanCalculateCore() {
return false; // Cannot calculate by default
}
protected virtual string CalculateCore() {
throw new NotImplementedException("Cannot calculate");
}
protected abstract string PerformCore();
#region IBusinessRules Members
public string Perform()
{
return PerformCore();
}
public bool CanCalculate
{
get { return CanCalculateCore(); }
}
public string Calculate()
{
return CalculateCore();
}
#endregion
}
So the call site now looks neat:
objBase = objfactory.GetObject(1);
if (objBase.CanCalculate) {
Console.WriteLine(objBase.Calculate());
}
One big problem of extending the interface is, it gives the caller no hint at all that you might support that interface as well.
This is a domain modelling issue and relates to what you mean by BusinessRule and IBase in your problem domain.
What is IBase? Sounds like it should be called IBusinessRule. In which case, what does Calculate mean in the context of a "business rule". If it has a generic meaning in your domain then IBusinessRule should implement it, as should the other classes, even if only as an empty method.
If it doesn't have generic meaning in your domain then your class should implement another interface ICalculable (IAlgorithm?) that has Calculate, which you call as:
ICalculable calculable = obj as ICalculable;
if ( calculable != null ) calculable.Calculate();

Categories