How to expose base class while keeping derived ones internal - c#

Hello i have the following problem:
I have a struct
public struct Cell
{
public Node Value;
public static implicit Cell(Node value)=>new Cell(value); //can't since node less accesible then cell
}
This struct Cell contains a property of type Node which is an abstract base class and currently is internal with all its derived classes.What i need is to somehow make the Cell struct accesible for other developers so that they can extract the value of the Node without knowing the Node derived class.
internal abstract class Node{
internal class ANode:Node{
public byte[] internalValue;
}
internal class BNode:Node{
public int internalValue;
}
}
How can i achieve this? The cell is exposed to outside and so should the abstract base class Node.The user should be able to implicit cast from Node to Cell.
Current approach
What i have tried so far is define an interface IRaw for Node that extracts the content from the Node derived classes.The explicit implementation is a virtual method ,overloaded in the derived classes.
interface IRaw{
byte[] GetRaw();
}
internal abstract class Node:IRaw
{
byte[] IRaw.GetRaw()=>this.GetRaw();
protected virtual byte[] GetRaw(){ ....}
}
internal class ANode:Node
{
protected override byte[] GetRaw()
{
.....
}
}
The problem in the above approach is that i can not pass the IRaw as argument in the Cell constructor with the error code:
user defined conversions to or from an interface are not allowed.
public struct Cell
{
public IRaw Value;
public static implicit Cell(IRaw value)=>new Cell(value);
}
Any suggestions ?I practically need a "Bridge" between the Cell which is public and the contents of Node which are internal.

You can simply make Node public and keep its derived classes internal. Unrelated to that, you should think about not deriving Node in nested classes for better maintainability:
public abstract class Node {
}
internal class ANode : Node {
public byte[] internalValue;
}
internal class BNode : Node {
public int internalValue;
}
If you want to be able to create instances of ANode and BNode from external assemblies, you can use an abstract factory:
public static class NodeFactory {
public Node CreateNode(byte[] value) {
return new ANode { internalValue = value };
}
public Node CreateNode(int value) {
return new BNode { internalValue = value };
}
}

Related

Create public property of internal class?

Suppose that I've this situation:
Base class or Mother class that declare this structure:
public static class Mother
{
private static Childs _child = new Childs();
public static Childs Child
{
get { return _child; }
}
}
How you can see I want implement a singleton base class for access to all methods in one place as: Mother.Child.SomeMethod.
With this structure I've a better code organization.
Now I want make the Childs class only as internal, so here start the problem 'cause I can't create a public property of an internal class. The structure of internal class is the following:
internal class Childs
{
public static bool SomeMethod() { ... }
}
so how can I make a public property of an internal class?
If the child is internal, the static access point should be internal as well.
If you actually want to have public access to some members of the child, consider using an interface.
Anyway, if there is a static access point, you don't need to make members static.
public static class Mother
{
private static Child _child = new Child();
public static IChild Child
{
get { return _child; }
}
}
public interface IChild
{
// public stuff here
bool SomeMethod();
}
internal class Child : IChild
{
public bool SomeMethod() { ... }
// additional internal members here
}
All classes in the inheritance tree must have at least the same visibility as the highest class in the hierarchy. There is no way to have a public class derive from an internal class.
Maybe your Childs class public. If you want to, you can make it abstract to prevent instantiating it or make the constructor internal to prevent deriving it in another assembly.
You cannot do that. If the property is public, any other class can access it. But if they are able to get it, they must also be able to access the class being received.

How to force others to obey a specific layout for a child class?

I have an abstract class as follows:
public abstract class Node
{
public abstract void run();
}
There are some child nodes that may have several properties as input and output. But all the operation is done just in run() method that each Node should implement. For example a Node that draws a line could be something like this:
public class LineNode : Node
{
[Input]
public Point a;
[Input]
public Point b;
[Output]
public Line line;
public override void run()
{
line = new Line(a, b);
// draw line ...
}
}
[AttributeUsage(AttributeTargets.Field)]
public class Input : System.Attribute
{
}
[AttributeUsage(AttributeTargets.Field)]
public class Output : System.Attribute
{
}
As you see I don't have any prior information about fields in the child classes. ** For a Node to be a valid node in convention, It is just required to have at least one output.** I want to force all other users to have at least one output in their Nodes so I can find it by reflection by looking for a field that [Output] attribute is applied to.
Is this possible?
And if this is, Is it the best way?
Thanks for any help
Here the same issue raised but the suggested solution settled it in the run time. I was looking for an Object Oriented solution though. Which one is more logical actually?
You could do something like this
public interface IRunnable<T>
{
T Run();
}
And then every class that implements this interface must provide this run method and return a (strongly typed ) result.
Or if the run method does not return the result
public interface IRunnable<T>
{
void Run();
T Value {get;}
}
public class LineNode : IRunnable<Line>
{
[Input]
public Point a;
[Input]
public Point b;
private Line line;
public Line Value { get{return line;}}
public override void run()
{
line = new Line(a, b);
// draw line ...
}
}
Define something like this in your base class:
public abstract class Node
{
[Output]
public abstract object DefaultOuptut;
public abstract void run();
}
And now your line class might look like this:
public class LineNode : Node
{
[Input]
public Point a;
[Input]
public Point b;
[Output]
public Line line;
[Output]
public override object DefaultOutput { get { return line; } }
public override void run()
{
line = new Line(a, b);
// draw line ...
}
}
You could use some generic typing as well on the default object:
public abstract class Node<T>
{
[Output]
public abstract T DefaultOutput;
public abstract void run();
}
This would still allow for other outputs that are not Ts.
How about using an Interface IOutputDefinition and defining an abstract ICollection<IOutputDefinition> in the Node-class. All Implementers have to fill this in order to enable your code to determine which outputs the implementation will produce.
You may define any Metadata-Properties like Name, Output-Type, ... or even a property containing a Getter-Expression for the Output in the Interface

How to automatically copy a property declaration to base class

I have a property A in all subclasses of base class Base.
How can I generate an abstract property definition of property A into base class Base?
I know ReSharper's refactoring Pull Members Up, but that moves the property to base class.
I need an abstract property in base class and a overriding properties in all sub classes. Is there a refactoring in Visual Studio or in ReSharper that can do it automatically for me?
There is a checkbox "Make abstract" for that in ReSharper Pull Members Up dialog :
I'm not sure Resharper can move up and create an abstraction as you want automatically, but you can atleast define it manually like this
In abstract class:
public abstract double A
{
get;
}
In Sub class:
public override double A
{
get
{
return 3.141;
}
}
It might be a clearner design to define a new Interface (or use an existing one) and define the property in the interface. That way, your existing subclasses won't have to use override.
public interface IInterface {
string MyProperty { get; }
}
public class Class : IInterface {
public string MyProperty { get; set; }
}
public abstract class AbstractClass {
public abstract string Value { get; }
}
public class ConcreteClass : AbstractClass {
private string m_Value;
public override string Value {
get { return m_Value; }
}
public void SetValue(string value) {
m_Value = value;
}
}
I hope this will be helpful to you.

Decorator pattern wasting memory

I have this base class having the following interface:
abstract class Base
{
abstract public object Val
{
get;
}
}
For any derived classes, Val's value must be specified at object creation time.
The question is: How can I make a derived class do this (hopefully at compile time)?
I tried adding a constructor:
abstract class Base
{
public Base(object value)
{
val = value;
}
private object val;
...
}
But as you can see then I had to declare a private field to store value in it (because Value is read-only).
The problem arises because I want to add some kind of effect to derived classes using the Decorator/Wrapper pattern introduced in GoF Design Patterns. But because I have declared the field inside Base class, the decorators keep saving a copy of the same data and I end up wasting memory.
Try this instead:
abstract class Base
{
public Base(object val)
{
this.Val = val;
}
public object Val { get; private set; }
}
That way, your derived class doesn't need its own field:
public class Derived : Base
{
public Derived(object val) : base(val) { }
}
If it is a decorator, then don't have a field:
public override object Val {
// add any decoration effects here if needed
get { return tail.Val; }
}
Where tail is the thing you are decorating.
However, it sounds like you mean inheritance (not decoration) - if so:
abstract class BaseClass {
protected BaseClass(object val) {...}
}
class ConcreteType : BaseClass {
public ConcreteType(object val)
: base(val) { }
}
Here the base class could even handle the storage etc.

How can I access a static property of type T in a generic class?

I am trying to accomplish the following scenario that the generic TestClassWrapper will be able to access static properties of classes it is made of (they will all derive from TestClass). Something like:
public class TestClass
{
public static int x = 5;
}
public class TestClassWrapper<T> where T : TestClass
{
public int test()
{
return T.x;
}
}
Gives the error:
'T' is a 'type parameter', which is not valid in the given context.
Any suggestions?
You can't, basically, at least not without reflection.
One option is to put a delegate in your constructor so that whoever creates an instance can specify how to get at it:
var wrapper = new TestClassWrapper<TestClass>(() => TestClass.x);
You could do it with reflection if necessary:
public class TestClassWrapper<T> where T : TestClass
{
private static readonly FieldInfo field = typeof(T).GetField("x");
public int test()
{
return (int) field.GetValue(null);
}
}
(Add appropriate binding flags if necessary.)
This isn't great, but at least you only need to look up the field once...
Surely you can just write this:
public int test()
{
return TestClass.x;
}
Even in a nontrivial example, you can't override a static field so will always call it from your known base class.
Why not just return TestClass.x?
Generics do not support anything related to static members, so that won't work. My advice would be: don't make it static. Assuming the field genuinely relates to the specific T, you could also use reflection:
return (int) typeof(T).GetField("x").GetValue(null);
but I don't recommend it.
Another solution is to simply not make it static, and work with the new() constraint on T to instantiate the object. Then you can work with an interface, and the wrapper can get the property out of any class that implements that interface:
public interface XExposer
{
Int32 X { get; }
}
public class TestClass : XExposer
{
public Int32 X { get { return 5;} }
}
public class XExposerWrapper<T> where T : XExposer, new()
{
public Int32 X
{
get { return new T().X; }
}
}
In fact, you can change that to public static Int32 X on the TestClassWrapper and simply get it out as Int32 fetchedX = XExposerWrapper<TestClass>.X;
Though since whatever code calls this will have to give the parameter T those same constraints, the wrapper class is pretty unnecessary at this point, since that calling code itself could also just execute new T().X and not bother with the wrapper.
Still, there are some interesting inheritance models where this kind of structure is useful. For example, an abstract class SuperClass<T> where T : SuperClass<T>, new() can both instantiate and return type T in its static functions, effectively allowing you to make inheritable static functions that adapt to the child classes (which would then need to be defined as class ChildClass : SuperClass<ChildClass>). By defining protected abstract functions / properties on the superclass, you can make functions that apply the same logic on any inherited object, but customized to that subclass according to its implementations of these abstracts. I use this for database classes where the table name and fetch query are implemented by the child class. Since the properties are protected, they are never exposed, either.
For example, on database classes, where the actual fetching logic is put in one central abstract class:
public abstract class DbClass<T> where T : DbClass<T>, new()
{
protected abstract String FetchQuery { get; }
protected abstract void Initialize(DatabaseRecord row);
public static T FetchObject(DatabaseSession dbSession, Int32 key)
{
T obj = new T();
DatabaseRecord record = dbSession.RetrieveRecord(obj.FetchQuery, key);
obj.Initialize(record);
return obj;
}
}
And the implementation:
public class User : DbClass<User>
{
public Int32 Key { get; private set;}
public String FirstName { get; set;}
public String LastName { get; set;}
protected override String FetchQuery
{ get { return "SELECT * FROM USER WHERE KEY = {0}";} }
protected override void Initialize(DatabaseRecord row)
{
this.Key = DbTools.SafeGetInt(row.GetField("KEY"));
this.FirstName = DbTools.SafeGetString(row.GetField("FIRST_NAME"));
this.LastName = DbTools.SafeGetString(row.GetField("LAST_NAME"));
}
}
This can be used as:
User usr = User.FetchObject(dbSession, userKey);
This is a rather simplified example, but as you see, this system allows a static function from the parent class to be called on the child class, to return an object of the child class.
T is a type, not parameter or variable so you cannot pick any value from any members. Here is a sample code.
public class UrlRecordService
{
public virtual void SaveSlug<T>(T entity) where T : ISlugSupport
{
if (entity == null)
throw new ArgumentNullException("entity");
int entityId = entity.Id;
string entityName = typeof(T).Name;
}
}
public interface ISlugSupport
{
int Id { get; set; }
}
cjk and Haris Hasan have the most-correct answers to the question as asked. However in this comment the OP implies that he is after something else not quite possible in C#: a way to define a contract for a static member in a derived class.
There isn't a way to strictly define this, but it is possible to set up a pattern that may be implied by a base class (or interface); e.g.:
public class TestClass
{
private static int x;
public virtual int StaticX => x;
}
or if not intended to be used directly
public abstract class AbstractTestClass
{
public abstract int StaticX {get;}
}
or (my preference in this contrived example)
public interface ITest
{
int StaticX {get;}
}
Elsewhere, this pattern of a StaticXxx member may be (loosely) associated with implementations that should back the member with static fields (as in TestClass above).
What's kind of fun is that this can be (re)exposed as static by the generic wrapper, because generic statics are isolated to each type used.
public class TestClassWrapper<T> where T : ITest, new()
{
private readonly static T testInstance = new T();
public static int test() => testInstance.x;
}
This uses a new() condition, but an associated static, generic factory pattern for creating ITest (or TestClass or AbstractTestClass) instances may also be used.
However this may not be feasible if you can't have long-lived instances of the class.
In this situation you assume that T is a subclass of TestClass. Subclasses of TestClass will not have the static int x.

Categories