# How do I extract interfaces from existing similar classes?

I have about 11 singleton-esque classes divided over a dozen files:

the first file is one that gathers all singleton definitions and makes them callable on a request scope:

public sealed partial class ExpertiseverslagEngine
{

ExpertiseverslagEngine()
{
_oService = CrmConnector.GetOrganization();
_oServiceContext = new XrmServiceContext(_oService);
}

public static ExpertiseverslagEngine Instance
{
get
{
{
if (UnitOfWorkHelper.CurrentDataStore["ExpertiseverslagEngine"] == null)
{
UnitOfWorkHelper.CurrentDataStore["ExpertiseverslagEngine"] = new ExpertiseverslagEngine();
}
return (ExpertiseverslagEngine)UnitOfWorkHelper.CurrentDataStore["ExpertiseverslagEngine"];
}
}
}
}

public sealed partial class OnderhoudEngine
{

OnderhoudEngine()
{
_oService = CrmConnector.GetOrganization();
_oServiceContext = new XrmServiceContext(_oService);
}

public static OnderhoudEngine Instance
{
get
{
{
if (UnitOfWorkHelper.CurrentDataStore["OnderhoudEngine"] == null)
{
UnitOfWorkHelper.CurrentDataStore["OnderhoudEngine"] = new OnderhoudEngine();
}
return (OnderhoudEngine)UnitOfWorkHelper.CurrentDataStore["OnderhoudEngine"];
}
}
}
}


The other 11 files are all but 1 built in this manner:

public partial class ExpertiseverslagEngine
{

public List<slfn_expertiseverslag> Retrieve_Active()
{
return (from exp in _oServiceContext.slfn_expertiseverslagSet
select exp).ToList();
}

public slfn_expertiseverslag Retrieve(Guid expertiseverslagId)
{
slfn_expertiseverslag expertiseverslag = (from exp in _oServiceContext.slfn_expertiseverslagSet
where exp.Id == expertiseverslagId
select exp).First();

return expertiseverslag;
}

{
where sbw.slfn_Expertiseverslag.Id == expertiseverslagGuid
select sbw).ToList();
return beschrijvingen;
}

public String Update(slfn_expertiseverslag oexpertiseverslag)
{
string status;
try
{

_oServiceContext.UpdateObject(oexpertiseverslag);
_oServiceContext.SaveChanges();
status = "Update gelukt";
}
catch (Exception e)
{
status = String.Format("Update mislukt, foutboodschap: {0}", e.Message);
}
return status;
}

public string Create(slfn_expertiseverslag expertiseverslag)
{
string status;
try
{
_oServiceContext.SaveChanges();
status = "Aanmaken gelukt";
}
catch (Exception e)
{
status = String.Format("Update mislukt, foutboodschap: {0}", e.Message);
}
return status;
}
}


Another example of one of these classes:

public partial class AssetEngine
{

public List<slfn_asset> Retrieve_Active()
{
return (from asset in _oServiceContext.slfn_assetSet
select asset).ToList();
}

public slfn_asset Retrieve(Guid assetId)
{
slfn_asset oAsset = (from asset in _oServiceContext.slfn_assetSet
where asset.Id == assetId
select asset).First();

return oAsset;
}

internal List<slfn_gebruikershistoriekasset> Retrieve_Geschiedenis(Guid assetId)
{
return (from gha in _oServiceContext.slfn_gebruikershistoriekassetSet
where gha.slfn_Asset.Id == assetId
select gha).ToList();
}

public string Update(slfn_asset oAsset)
{
string status;
try
{
_oServiceContext.UpdateObject(oAsset);
_oServiceContext.SaveChanges();
status = "Update gelukt.";
}
catch (Exception e)
{
status = String.Format("Update mislukt, Foutmelding: {0}", e.Message);
}
return status;
}

public string Create(slfn_asset asset)
{
string status;
try
{

_oServiceContext.SaveChanges();
status = "Aanmaken gelukt.";
}
catch (Exception e)
{
status = String.Format("Aanmaken mislukt, Foutmelding: {0}.", e.Message);
}
return status;
}
}


The final one is for a different purpose and looks like this:

public sealed partial class OptionsetEngine
{
{
// Use the RetrieveOptionSetRequest message to retrieve
// a global option set by it's name.
RetrieveOptionSetRequest retrieveOptionSetRequest =
new RetrieveOptionSetRequest
{
Name = optionsetName
};

// Execute the request.
RetrieveOptionSetResponse retrieveOptionSetResponse =
(RetrieveOptionSetResponse)_oService.Execute(
retrieveOptionSetRequest);

// Get the current options list for the retrieved attribute.
}

public List<OptionMetadata> GetLocalOptionset(string entityName, string attributeName)
{

RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest
{

EntityLogicalName = entityName,

LogicalName = attributeName,

RetrieveAsIfPublished = true

};
// Execute the request.
RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)_oService.Execute(retrieveAttributeRequest);
// Access the retrieved attribute.
// Get the current options list for the retrieved attribute.
{
{
// Get the current options list for the retrieved attribute.
{
}
return optionlist;
}

public IEnumerable<Entity> Retrieve_Assist_Entities(string entityName)
{
return _oServiceContext.CreateQuery(entityName).ToList();
}
}


As you can tell, this is for development of a Dynamics CRM 2011 extension outside the website platform. I have 11 of these engines, and apart from the final one mentioned above, they all have the same methods and variables in them.

i'm wondering if it's worth it to extract an interface (something like an IEntityEngine) so additional engines can be added more easily, and how to go ahead with that. I see 2 difficulties:

1. The clases are split over 2 files, so that might cause some difficulties extracting an interface;
2. each engine is intended for a different entity type, and has to return a different early bound entity;

Extracting an interface essentially boils down to taking the signatures for all public members, making them part of the interface you're extracting, and then making the type implement the interface you've extracted.

Tools like ReSharper work amazingly well for this (the partial class is handled, no sweat - in fact, the interface only needs to be specified in one place, if it's in both files one of them is redundant):

But before you start extracting interfaces, you should ask yourself why you have 11 classes that are essentially identical. Wouldn't a generic class make your life easier? It could implement a generic interface, which could look like this:

public interface IEngine<T, U>
{
IEnumerable<T> RetrieveActive();
T Retrieve(Guid id);
string Update(T value);
string Create(T value);
}


Where T would be slfn_expertiseverslag and U would be slfn_schadebeschrijvingwagen, but then the type parameters would need perhaps better names.

Note that I'm exposing IEnumerable<T>, not List<T> - if the goal of the method is to expose data that's meant to be consumed you should expose IEnumerable<T>. Expose a List<T> when the client code needs to be able to Add() and Remove() items.

There's a problem with your naming. slfn_expertiseverslag and slfn_schadebeschrijvingwagen don't follow naming conventions for types. Should be PascalCase, no underscores (save snake_case for ;).

As to address whether it's worth it to extract an interface, I can't really tell (it could very well be just additional complexity). I think making your class generic would definitely be helpful though.

• The reason the naming is all lowercase is because this is a Dynamics CRM 2011 custom entity. that slfn_ is a prefix which is automatically added when you make the entity, I cannot change that. I'm also going to give an example of another class to show that 1 generic class won't work without a redesign of the code. – Nzall Feb 27 '14 at 7:34
• If you mean entity as in database table, and you're using Entity Framework, mapping POCO class ABC to database table XYZ is fairly easy; an entity doesn't have to be named exactly as the db table it's mapped to. I'll take a look at your updated code later today ;) – Mathieu Guindon Feb 27 '14 at 18:57
• I mean Entity as in a Dynamics CRM% 2011 Entity, from Microsoft.Xrm.Sdk.Entity. I don't think that's related to the Entity Framework. – Nzall Feb 28 '14 at 7:41