Mixing encapsulation and dependency injection - c#

I have a class that serves as a data model. I'll simplify it like this:
public class DataModel
{
public bool IsDataModelActive {get; internal set;}
}
So the programmers who will use my DLL will only see what they need without risking to break anything.
On the flipside, I want to use DI in my classes that use DataModel. So I have to create an interface:
public interface IDataModel
{
bool IsDataModelActive {get;}
}
And so I inject this in my class:
public class Class1
{
IDataModel dataModel;
public Class1(IDataModel dataModel)
{
this.dataModel = dataModel
}
}
In this case, it is impossible for me to access the setter of dataModel.IsDataModelActive.
The best patch I've found is to cast after receiving the injection:
public class Class1
{
DataModel dataModel;
public Class1(IDataModel dataModel)
{
this.dataModel = (DataModel)dataModel
}
}
This helps for the unit tests, but it kind of break the whole concept of DI. What if I have another class that implements IDataModel?
What strategy do you/would you use?

If the interface IDataModel doesn't allow you to access the setter from outside of the DataModel, then (hopefully not surprisingly) you shouldn't need to access the setter from outside of the DataModel. Either the DataModel itself or something that can see the setter should be responsible for setting that value.

Is Class1 publicly visible - i.e. exposed to the consumers? If not, then create another internal interface IDataModelInt : IDataModel and provide setter there. Use the second one for your internal work.

Related

Should all public methods be declared in the interface?

Given an interface like:
public interface IFoo
{
string Bar();
}
And a class that implements it like:
public class Foo : IFoo
{
public string Bar()
{
returns "Bar";
}
public string SomeOtherMethod()
{
returns "Something else";
}
}
Is there a problem with this code? Should we add all methods to the interface?
One example: imagine a private method that grows complex enough to need unit tests. Could you make it public (so it can be called from the test project) but not add it to the interface (because no clients need to call it)?
If what a class does is simple enough that we can test its public methods and private methods at the same time, then we can just test the public methods.
If the private method grows so complex that between the public and private method we need too many combinations of tests then it's time to separate the private method into its own class. Making the private method public would break the encapsulation of the class. Even if we don't add the method to an interface, making the class method public still adds the method to the public interface of the class itself.
So if we have this:
public class ClassWithComplexPrivateMethod
{
public void DoSomething(int value)
{
PrivateMethodThatNeedsItsOwnTests(value);
}
private string PrivateMethodThatNeedsItsOwnTests(int value)
{
// This method has gotten really complicated!
return value.ToString();
}
}
We might refactor to something like this:
public interface IRepresentsWhatThePrivateMethodDid
{
string MethodThatNeedsItsOwnTests(int value);
}
public class RefactoredClass
{
private readonly IRepresentsWhatThePrivateMethodDid _dependency;
public RefactoredClass(IRepresentsWhatThePrivateMethodDid dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency.MethodThatNeedsItsOwnTests(value);
}
}
And now a new class implements IRepresentsWhatThePrivateMethodDid.
Now when we test the refactored class we mock IRepresentsWhatThePrivateMethodDid, and we write separate unit tests for any classes that implement IRepresentsWhatThePrivateMethodDid.
It may seem like a contradiction to say that exposing the private method as public breaks encapsulation, but exposing it as its own separate class doesn't. There are two differences:
The refactored class doesn't depend on the new class containing what used to be the private method. It depends on the new interface.
The interaction between the refactored class and the interface is still hidden within its methods. Other classes that call its public methods don't "know" about how it uses its dependency. (In fact, other classes will likely depend on abstractions instead of directly on the refactored class.)
It's also easy to get carried away with this and introduce the separate dependency too soon, when we could have tested the class - including its private methods - through the public methods. I've done this lots of times, and it can result in lots and lots of unnecessary interfaces and extra classes. There's no perfection, just our best efforts to balance it.
One more thought: We tend to use interfaces to represent dependencies, but we don't have to. If what we're extracting was just a single private method, then perhaps we can represent it with a delegate or a Func instead, like this:
public class RefactoredClass
{
private readonly Func<int, string> _dependency;
public RefactoredClass(Func<int, string> dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency(value);
}
}
Or we can use a delegate, which I like better than Func because it indicates what the function does.
Generally when a class implements an interface all members of an interface must be implemented, it does not go the other way around.
Also when implementing an interface member, the corresponding member of the implementing class must be public, non-static, and have the same name and parameter signature as the interface member. You can have methods, even public, in the class that are not defined in the interface.
On top of that, the interface itself provides no functionality that a class or struct can inherit in the way that it can inherit base class functionality. However, if a base class implements an interface, any class that's derived from the base class inherits that implementation.
Interface should represent just the required API without regard to unit-testing and smth else.
To test public-methods of class you should do nothing because Test-project has access to them. You just need to instantiate a class and inject all required dependency using Mock.
Example: testing class without any dependencies
Example: testing class with dependency
To test private methods of a class need to make them visible to test-project:
mark private methods as internal
make internal-method visible to test-project: add to AssemblyInfo.cs the directive [assembly: InternalsVisibleTo("Project.Tests")] (see InternalsVisibleToAttribute)

C# Interface with static property or methods?

I need to define a static property or method in certain classes of my bussiness logic, to explicity determine which classes are cacheables in Session or Cache of ASP.NET service. I'm thinking, static property or method in the interface would be perfect, but C# 4.0 doesn't support this.
All a need is be able to evaluate in a generic manager which classes are cacheables and, if they are, at what level: session (user) or cache (application).
Now I'm trying with a empty interface with T parameter to evaluate, but, maybe exists a better approach?? Thanks.
public interface ICacheable<T>
{
}
public class Country : ICacheable<CacheApplication>
{
}
public class Department : ICacheable<CacheUser>
{
}
public class Gestor<T>
{
// ...
if (typeof(T) is ICacheable<CacheApplication>)
{
}
// ...
}
How about using a custom attribute? Your classes then would look something like this:
[Cacheable(Level = CacheLevels.Application)]
public class Country { }
[Cacheable(Level = CacheLevels.User)]
public class Department { }
You can read here on how to create your own custom attribute and then access its value by using reflection.
You cant define static interfaces, for one thing, you cant make instances of static classes so you cant substitute them for others with the same base class.
You might be better off having a singleton instance of one class and using interfaces as normal. You could enforce one and one-only instance through a factory pattern too.

How to hide set method of an implemented property from an interface in C#?

Greetings everyone...
If I have the following interface:
interface IMyInterface
{
int property { get; set; }
}
And the following implementation:
class MyClass : IMyInterface
{
// anything
}
How can I hide the set method of property from the instances of MyClass... In other words, I don't want the set method of property to be public, is that possible?
It would be easy to do with abstract class:
abstract class IMyInterface
{
int property { get; protected set; }
}
Then I could only set the property within the class that implements the abstract class above...
Don't have the set in the interface to begin with. You can still implement it as private.
You can't "hide" it, it's part of the contract. If you don't want it to be part of the contract, don't define it.
If you use the following interface the set method will be unavailable when classes are manipulated via the interface:
interface IMyInterface
{
int property { get; }
}
You could then implement the class like this:
class MyClass : IMyInterface
{
int property { get; protected set; }
}
If some implementations will only implement some parts of an interface, it may be a good idea to subdivide the interface into the parts which each implementation will either implement completely or not at all, and then define interfaces which inherit all the common combinations of them. Adapting your example:
interface IMyReadableInterface
{
int property { get; }
}
interface IMyFullInterface : IMyReadableInterface
{
new int property { get; set; }
}
Classes which want to support read-write access should implement IMyFullInterface; those which want to only support read access should only implement IMyReadableInterface. This segregation will not require any extra work for implementations of either interface which are written in C# and implement property implicitly. Code which implements property in VB, or explicitly implements property in C#, will have to define two implementations of property--a read-only one and a read-write one, but such is life. Note that while one could define an IMyWritableInterface which just had a setter, and have IMyFullInterface inherit both IMyReadableInterface and IMyWritableInterface, IMyFullInterface would still have to define a read-write property of its own, and when using explicit implementation one would then have to define three properties (I really don't understand why C# can't use a read-only and write-only property together as thought they were a read-write property, but it can't).
Assuming you need the setter to be part of the interface but for some reason it does not make sense for it to be used on a particular implementer (in this case MyClass) you can always throw an exception in the setter (such as an InvalidOperationException). This will not protect you at compile time, only at run time. It is a bit strange though, as code that operates on the interface has no idea whether calling the setter is allowed.
There are certainly cases where you want the interface to have a set and then hide it in some concrete class.
I believe the code below shows what we want to accomplish. I.e. the implementation hides the setter, but any IMyInterface aware component will have access to it.
public static void Main()
{
var myClass = new MyClass();
myClass.Property = 123; // Error
((IMyInterface)myClass).Property = 123; // OK
}
It's basically the same pattern you often see for IDisposable.Dispose() where you have an Explicit Interface Implementation. Here's an example for completeness.
public interface IMyInterface
{
int Property { get; set; }
}
public class MyClass : IMyInterface, IDisposable
{
public int Property { get; private set; }
int IMyInterface.Property
{
get => Property;
set => Property = value;
}
void IDisposable.Dispose() {}
}
Too much typing :(
C# doesn't help us much here. Ideally, it would be possible to have an explicit interface implementation for the setter:
// In C# 10 maybe we can do this instead:
public class MyFutureClass : IMyInterface
{
public int Property { get; IMyInterface.set; }
}
See C# feature proposal here.
There is no protected or private in interface, everything is public. Either you don't define any set or use it as public.

Auto Property that returns an interface

This is something curious that I saw in my coding today.
Here is the sample code:
public class SomeClass
{
public IUtils UtilitiesProperty { get; set; }
}
public interface IUtils
{
void DoSomething();
}
public class Utils : IUtils
{
void DoSomething();
}
This compiles fine.
So what is UtilitiesProperty? Is it a Util? What if more than one class implemented IUTil? Would it fail the compile then?
It doesn't have any value until you give it one (or rather, it has the value null). If you assign it a Utils reference, then yes: it is a Utils, exposed via the IUtils interface. You can only give it null or things that implement IUtils.
It's a property that can hold an object that implements your IUtils interface. More classes can implement this interface and using the interface allows you a level of abstraction (the consumer doesn't care as long as the class adheres to the interface contract).
I'd suggest you read up on the use of interfaces, abstract classes and the like.
For example the MSDN docs.

Is it possible to have 2 Base class's which already inherit from something inherit or know of a third common class?

I have 2 class's
Class 1.
public class BaseContentPage : System.Web.UI.Page
{
}
Class 2.
public class BaseUserControl : System.Web.UI.UserControl
{
}
And now i want them to be aware of this class.
public class BaseCommon
{
public string Variable1 { get; set; }
public string Variable2 { get; set; }
public string Variable3 { get; set; }
}
How I'm currently doing it is by making the variables of the BaseCommon class static like so
public static string Variable1 { get; set; }
public static string Variable2 { get; set; }
public static string Variable3 { get; set; }
How else can i do this?
Use composition.
Give BaseContentPage and BaseUserControl a private field (which can be exposed as a property if needed) of type BaseCommon (don't make it static).
They can either create BaseCommon or have an instance passed in through the constructor (Dependency Injection).
First off, I don't think you want the BaseCommon properties to be static. The properties are then global across the application so changing them from one instance will change them for all instances.
What you're talking about is multiple inheritence and it isn't supported by c#. You'd be better off changing BaseCommon to be an interface and having BaseContentPage and BaseUserControl implement that interface.
If they are static, does that mean that this third class is a global resource? You could look at Singleton or IoC containers or pass the instance to the other classes when constructed.
You need to give more concrete examples of what this common "base" data that you are adding to two different parts of your object inheritance tree are.
Conceivably, say each instance really just has similar data (an example I'm thinking of is internationalization, say, which is used to customize both a page and a usercontrol according to phrase IDs, etc which are specific in context), then what you can do is have a class I18nSettings which implements II18nSettings. Then in each class, encapsulate an I18nSettings instance and implement II18nSettings and pass them through. Alternatively, you can expose the internal I18nSettings instance. I've even just defined an interface and had each class implement it - it was not worth having a separate class at all.
There are other options to do this kind of thing - it depends on whether the concrete classes you are inheriting from implement a lot more useful things than the things you are adding. It might make more sense to inherit from your concrete class and implement other interfaces so that the class can be used in other places.

Categories