Prevent access to inherited members - c#

This question might be a bit odd. The scenario is as follows:
There is an interface for plugins called IPlugin
There is an abstract base class for plugins (which implements the interface) called PluginBase
These are stored inside a class library
Now everyone should be able to create their own plugins by creating a new class library and a plugin class which derives from PluginBase.
The PluginBase class will provide many public properties which are used from the base tool to communicate with the plugin interface. This is done by reflection; the tool searches for a class which is based on the interface IPlugin and creates an instance of that class.
Now the problem is that these public properties are necessary for the plugin mechanism but should not be accessed or changed from the derived plugin class. In short: the user-defined plugin class should not be able to access several public members of its base class PluginBase.
Is this possible somehow? I know that I normally should use private for those properties (so the derived class can't access them) but as the base class also acts as a plugin interface, this is not possible.
Solution (based on answers of Fabjan and Luaan):
// basic plugin interface (IPlugin.dll)
public interface IPlugin
{
// plugin communication interface
string SomeProperty { get; set; }
void SomeMethod();
// public interface
string Name { get; }
void Run();
}
// plugin base class (IPlugin.dll)
public class PluginBase : IPlugin
{
string IPlugin.SomeProperty
{
get { return "Something"; }
set { /* ... */ }
}
void IPlugin.SomeMethod()
{
Console.WriteLine("Something");
}
public string Name
{
get { return "MyName"; }
}
public void Run()
{
// ...
}
}
// user-defined plugin (MyPlugin.dll)
public class MyPlugin : PluginBase
{
public MyPlugin()
{
// will not work
this.SomeProperty ...
}
}
// main assembly
static void Main(string[] args)
{
Assembly asm = Assembly.LoadFrom(#"path\to\assembly");
var type = asm.GetTypes().FirstOrDefault(t => t.GetInterface("NamespaceOfIPlugin.IPlugin", true) != null);
NamespaceOfIPlugin.IPlugin plugin = (NamespaceOfIPlugin.IPlugin)Activator.CreateInstance(type);
// works as expected
plugin.SomeMethod();
}

If you don't want the properties to be public, don't make them public.
The architecture of your solution seems to be wonky at best. You expect (require even) all plugins to implement PluginBase, yet you search for plugins based on the IPlugin interface. Why? Pick one, and roll with it. There's no rule in the framework that plugins must be searched for based on some interface.
To prevent a derived class from accessing the members of its parents, you use the private access modifier. If your plugin manager needs to have access to those values, you must make sure it actually does - for example, you could make the part responsible for working with this data a sealed nested class of PluginBase.
But in the end, the question is - why? There's little point in trying to force the derived classes to avoid accessing those members (why have those members in the first place?). Perhaps it would be enough to have those properties in an interface that would be implemented explicitly? That way you could still use e.g. ((IPluginBase)plugin).SomeProperty, but not plugin.SomeProperty. It's not like they couldn't get to the data using reflection anyway.

Now the problem is that these public properties are necessary for the
plugin mechanism but should not be accessed or changed from the
derived plugin class.
What you try to do isn't really possible because if class implements abstract class - it must know all its members. What you can do is you can do something like this:
1) Add internal keyword for your interface
internal interface IPlugin
{
int MyProperty1 {get; set;}
int MyProperty2 {get; set;}
int MyProperty3 {get; set;}
void HiddenMethod();
}
2) Implement properties/methods that you want to hide explicitly :
abstract class PluginBase : IPlugin
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
int IPlugin.MyProperty3 { get; set; }
void IPlugin.HiddenMethod() {}
}
Now you can use all your hidden methods and properties in your main solution via IPlugin interface by casting to it:
IPlugin instance = new MyConcretePlugin();
instance.MyProperty3 = 10;
instance.HiddenMethod();
IPlugin interface now is not accessible from any other solution (except one that holds it) and therefore same are for all hidden members.

you could use internal on the methods and properties that only should be available from within the assembly
public class PluginBase : IPlugin
{
// Only accessible within the same assembly
internal static int x = 0;
}

You can use InternalsVisibleToAttribute.enter link description here

Related

Is there a way to hide or override a base class member variable (itself a class) in its derived class in C#?

I have an app that uses a set of dll's from a 3rdparty. I am trying to incorporate an updated version of the dll's that have changed some variables and parameters from int to uints. I think I can easily capture base class events in my derived class and re-throw modified events, but I am not sure of an easy way to handle the direct access of the variables in the base class's member class.
The example below shows the original 3rd party implementation. In the latest version, the member variables of ThirdPartyNumberPair are now uint's. I'm looking for a way to intercept the MyNumberPair.x and .y access in my derived container and do the conversion so I don't have to modify SomeMethod - mainly because it is used in many places.
public class ThirdPartyNumberPair
{
public int x{ get; set; };
public int y{ get; set; };
}
public class ThirdPartyContainer
{
public ThirdPartyNumberPair MyNumberPair;
}
public class MyDerivedContainer : ThirdPartyContainer
{
...
}
public class MyClass
{
public MyDerivedContainer myContainer;
public void MyMethod(){
int i = myContainer.MyNumberPair.x;
myContainer.MyNumberPair.y = 3;
}
}
I've tried creating a derived MyThirdPartyNumberPair and hiding the base ThirdPartyNumberPair, but I didn't find any easy way of getting those values to the base ThirdPartyNumberPair member.

Get derived (generic) class members from base class (or shared interface) reference

I am struggling to formulate my question properly, I hope I can clarify it through the following description:
I have an abstract generic base class that is supposed to describe a specific container item, upon other things, and another abstract class of the same name to reference the generic classes by. I also created an interface to reference them by, both work but still result in the same issue eventually. For this example i am using the shared base class
public abstract class ItemEditorState
{
}
and the derived generic class
public abstract class ItemEditorState<T> : ItemEditorState where T : Item
{
public abstract SimpleDatabase<T> Items { get; set; }
public abstract void DoStuff();
...
}
So far so good.
Now I have classes deriving from ItemEditorState<T> corresponding to different Items.
public class EditorStateItemA : ItemEditorState<ItemA>
{
private ItemADatabase _itemADatabase; //ItemADatabase is public class ItemADatabase : SimpleDatabase<ItemA> {}
public override SimpleDatabase<ItemA> Items { get => _itemADatabase; set => _itemADatabase = value; }
public override void DoStuff(){}
...
}
So far so good again.
Now I have a static manager class holding a List<ItemEditorState> of references to all ItemEditorStates, such as EditorStateItemA, EditorStateItemB etc.
public static class ItemEditorStateManager
{
public static List<ItemEditorState> itemEditorStates = new List<ItemEditorState>();
public int GetState(int index) => itemEditorStates[index];
}
But since I reference the derived class instances by the shared abstract base class (or in another case the IItemEditorState interface), I can't access any members.
What I would like to do is access the Items list of any of EditorStateItemA or EditorStateItemB within the list in the ItemEditorStateManagerfrom the ItemEditorStateManager.GetState(index) method.
I know I would probably have to cast it to the proper class first, but I don't know the specific type at that point. I am sure my architecture is off, but I can't wrap my head around it.

C# Is there a way of implementing interfaces for classes from dlls?

I'm using a dll with a lot of classes. I'd like to implement dinamically interfaces for these classes, then I can unit test them by mock.
Is there a way of doing it?
Example:
The dll has a class Comunicator
public class Comunicator
{
public void Execute()
{
//execute something
}
}
Is there a way of doing this class implementing the interface below dinamically?
public interface IComunicator
{
void Execute();
}
This way I want that the property below
public IComunicator Comunicator{ get; set; }
Be able to understand this assignment
Comunicator = new Comunicator();
Is there a way of doing this class implementing the interface below dynamically?
Short Answer: NO
If the dll is a 3rd party library then there is nothing you can do to modify that class as you have no control over it.
You could however create your own classes and abstraction to encapsulate the 3rd party dependency.
You create your desired interface
public interface IComunicator {
void Execute();
}
And either using encapsulation
public class MyCommunicator : ICommunicator {
private readonly Communicator communicator = new communicator();
public void Execute() {
communicator.Execute();
}
}
or inheritance (if the class is not sealed)
public class MyCommunicator : Communicator, ICommunicator {
}
This way the property below
public IComunicator Comunicator{ get; set; }
Will be able to understand this assignment
obj.Comunicator = new MyComunicator();

Implement common behaviour in alternative to abstract base classes?

In C#, I have a class hierarchy with a couple of abstract base classes near the top and a fair number of derived classes. A few these concrete classes have some common properties and methods that are implemented identically. It strikes me as wasteful and so one solution might be to implement this common behaviour in another abstract base class.
abstract class Control;
abstract class SquareControl: Control
{
public int SquarishProperty;
public void SquarishMethod();
};
class Window: SquareControl;
class Button: SquareControl;
However, what if several other classes in the hierarchy shared some other behaviour but also share something in common with one of the controls from another base class? Perhaps there are lots of areas of commonality. It would become impractical to model this with abstract base class implementation wouldn't it?
abstract class FlashableControl: Control
{
public int FlashyProperty;
public void FlashMethod();
};
class StatusBar: FlashableControl; // but it's also a bit square too, hmm...
So how do you go about sharing such implementations across classes without using base classes?
I imagine I want to delegate the implementaion of an interface to another class and have that class implement those properties and methods on behalf of the desired classes, so that to the user, the StatusBar and Window appear to support a standard interface, but under the covers it's something else that implements it.
I can visualise aggregating classes that implement this behaviour, but is this appropriate and are there any pitfalls? What are the alternatives?
Thanks
You can use a pattern like this:
public interface ICommonServices
{
string SomeProperty { get; set; }
void SomeMethod(string param);
}
public static class CommonServiceMethods
{
public static void DoSomething(this ICommonServices services, string param)
{
services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
}
}
All classes that implement ICommonServices now also get some free behavior via the extension method, which depends solely on those features exposed by all ICommonServices implementers. If you need access to base class functionality, you can put that in its own interface and have ICommonServices implement that interface as well. Now you can create 'default' extension functionality for interfaces without having to use multiple base classes.
EDIT
If you want some of these methods to be internal, you can modify the pattern like this:
public class MyObject : IServices
{
public string PublicProperty { get; private set; }
string IServices.SomeProperty { get; set; }
void IServices.SomeMethod(string param)
{
//Do something...
}
}
public interface IPublicServices
{
string PublicProperty { get; }
}
internal interface IServices : IPublicServices
{
string SomeProperty { get; set; }
void SomeMethod(string param);
}
internal static class ServiceMethods
{
public static void DoSomething(this IServices services, string param)
{
services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
}
}
Basically we're exposing both public and internal interfaces. Note that we implement the internal interface methods explicitly, so that the methods are not available for public consumption (since the public client can't get access to the interface type.) In this case, the helper extension methods are internal, relying on the internal interface, though you could also create public helper methods that rely on the public interface.
You could use 'has-a' instead of 'is-a' and delegate to an internal square control
class Window : Control, ISquareControl
{
private SquareControl square;
public void SquareOperation()
{
square.SquareOperation();
}
}
class SquareControl : Control, ISquareControl
{
public void SquareOperation()
{
// ...
}
}
One way is to use Interfaces and Base Classes.
Flashable would make a good Interface instead of a class.

How to use a class as the base, but hide the class type publically?

I am currently just exposing the properties through a generic interface e.g.
public interface IBaseClass
{
int ID { get; set; }
}
internal class MyBaseClass : IBaseClass
{
public MyBaseClass() { }
public int ID { get; set; }
}
public class MyExposedClass : IBaseClass
{
private MyBaseClass _base = new MyBaseClass();
public int ID
{
get { return _base.ID; }
set { _base.ID = value; }
}
}
Then in my main application I can do:
IBaseClass c = new MyExposedClass();
c.ID = 12345;
But can't do:
MyBaseClass b = new MyBaseClass();
This is my desired behaviour.
However, I was just wondering if this is the correct approach? Or if there was a better way?
If you only want to prevent instantiation you could make MyBaseClass abstract (make it's constructor protected as well - it is a good design) and have MyExposedClass derive from it. If you want to completely hide the type your approach seems fine.
This look fine to me. Making small interfaces makes it easier to write decoupled code.
I don't know if this will help, but you can make your base class protected internal. This would mean that any internal class has access to it as if it were public, or any class (from within and without the assembly) can subclass the base class. It won't prevent people from implementing their own sub class though.
Alternatively, exposing through an Interface would be the best way I'd think.
For this you can opt for explicit implementation like this:
public interface IBaseClass
{
int ID { get; set; }
}
internal class MyBaseClass : IBaseClass
{
public MyBaseClass() { }
public int IBaseClass.ID { get; set; }
}
public class MyExposedClass : IBaseClass
{
private MyBaseClass _base = new MyBaseClass();
public int IBaseClass.ID
{
get { return _base.ID; }
set { _base.ID = value; }
}
}
You can refer to a similar post C# Interfaces. Implicit implementation versus Explicit implementation
Make your base class abstract.
You could expose the interface as public, implement an internal sealed implementation of that class, and use a factory approach to build instances of the desired interface. That way the client will never know when you change your implementation, or if you have multiple implementations of the same base interface plugged in the factory. You could also eliminate the set accessors in the interface and put them in the internal implementation to only expose the properties to the outside world. That way the exterior code has to make less assumptions over your implementation and you are better isolated. Please correct me if I'm having a poor/bad image of this approach.
Edit: The factory would be public and you'd need some sort of "transfer object" to pass data to the factory. That transfer object implementation would be public, together with it's interface.
Your example seems to include a poor example of taking advantage of inheritence. Since you included a single property it and couldnt come up with a better example i am guessing that its real. I would suggest in this case forget the base class and stick the property on the derived.

Categories

Resources