سؤال

I have a series of classes in a project which all do essentially the same thing but on different objects. Due to some of them having been coded at different times and by different people there is some inconsistency in naming. I want to update my code in a manner that will enforce some consistency not only in the current objects but new ones that are created in the future. My understanding of programming leads me to believe that I need either a base class or an interface but I can't figure out how to get either to work. The methods I want to have are:

internal BusinessObject MethodA(EntityObject entity)
internal Void MethodB(EntityContext context, BusinessObject obj, EntityObject entity)

The issue I am having is that in each class the "BusinessObject" and "EntityObject" will be different e.g. in one it might be "CarObject and CarEntity" and in another it would be "BusObject and BusEntity". I still want the two methods and I still want them named MethodA and MethodB I just want to swap out the actual object types in the implementation. The implementations themselves will be different because they are using different objects.

I know the object types at compile time and need to be able to access the properties of the objects so if generics are used I need to cast the generic as the correct type in the implementation. Also the implementation of MethodA requires creating a "new" BusinessObject i.e. "BusinessObject x = new BusinessObject()" if that makes any difference.

I tried using an interface with generics in the methods and also a base class with abstract methods but I haven't been able to figure out how to get either to work.

What is the best way to handle this? Sample code would be much appreciated.

هل كانت مفيدة؟

المحلول

Generics are the way

So I would declare an interface (or base class if you prefer that route) along these lines:

internal interface IEntityContext<TEntity>
{
 ???
}

internal interface IMyInterfaceName<TEntity, TBusinessObject>
{
TBusinessObject MethodA(TEntity entity);
Void MethodB(IEntityContext<TEntity> context, TBusinessObject obj, TEntity entity);
}

Then when it comes to implementing you class:

class MyClassThatDoesThisStuff : IMyInterfaceName<Farm, FarmBo>
{
    internal FarmBo MethodA(Farm entity);
    internal Void MethodB(IEntityContext<Farm> context, FarmBo obj, Farm entity);

}

etc...

You can also enforce that your classes descend from something:

interface IMyInterfaceName<TEntity, TBusinessObject> 
            where TEntity : EntityBase,
                  TBusinessObject : BusinessObjectBase
{
...
}

نصائح أخرى

Just to show the solution with an abstract base class, see Neils answer for more information...

public abstract class BaseClass<A,B> {
    internal abstract A MethodA(B entity);
    internal abstract void MethodB(EntityContext context, A obj, B entity);
}

Then extend this class:

public class AClass : BaseClass<BusinessObject, EntityObject> {
    internal override BusinessObject MethodA(EntityObject entity) {...}
    internal override void MethodB(EntityContext ctx, BusinessObject obj, EntityObject entity) {...}
}

There are really three approaches:

  1. Generics: Where you specify container object in such a way as it is independent of the types of BusinessObject and EntityObject. You can extend that a little to place restrictions on the types of objects that the generic accepts as a parameter with generic constraints. The big challenge is that it is difficult to actually use BusinessObject and EntityObject without casting and other relatively unsafe operations.

  2. Inheritance: In this case, you implement BusinessObject as a base class, and require that all objects used as a parameter be derived from that, and similarly with EntityObject. Then you can put any methods that you actually need to use in the base class (and if necessary override them in the derived classes.)

  3. Interfaces: This is a half way between the two. Here you say that BusinessObject and EntityObject are interfaces (tradtionally their names will begin with I, as in IBusinessObject etc.) Here you specify in the interface the methods that you require any BusinessObject or EntityObject to implement, and can consequently call them in your container object.

So with the limited information you give it is impossible to say which is most appropriate. However, those are your three basic choices.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top