0

Context

My projects are separated into one assembly with Interfaces, which I call the Core, and another assembly with the implementation, which I call the Implementation. In reality, the namespaces look like this:

CompanyName.ProjectName.Core
CompanyName.ProjectName

The first project has zero business logic in it (May or may not have "domain" logic, logic related to the basic instantiation and validation of models). The second project has all of the business logic in it (May or may not have "domain" logic, as I define it here).

Any other projects in any other systems which wish to consume this domain would implement only the Core and nothing else. From there, it can define usage of the interfaces and models defined within.

Any other Startup Projects would have to also consume SOME version of Implementation, in order to perform Dependency-Injection on their classes which are consuming the Core. It is likely that they will be consuming the Implementation project I defined above... especially if it is the only implementation of its related Core.

The Problem

In general I don't distribute my implementation unless it is paid for. This allows users to freely review, navigate, and implement a Core of my product, without the actual proprietary implementation unless they buy it.

In this one case, I have created some Abstract Base Classes which contain a lot of boiler plate implementation of the Core Interfaces. For all intents and purposes, this assembly with the Base Classes is the Implementation project, which I do not want unauthorized users to have access to.

However, I need them to have access to the definitions of the Abstract Classes so they can implement them. So technically, they are Core Material. Contracts, if you will.

My Failed Solution 1

Idea 1 is to define the Abstract Class in the Core project, but make all of the Virtual methods throw not implemented exceptions.

If I create the class: CompanyName.ProjectName.Core.BaseClass(), then the consumer will implement that class. Then when I later consume their libraries, my Actual CompanyName.ProjectName.BaseClass() wouldn't be recognized as the same object.

If I create the class: CompanyName.ProjectName.BaseClass() inside my Core assembly, then when I later consume their libraries, my Actual implementation will throw an exception that there are two instances of CompanyName.ProjectName.BaseClass(), and it doesn't know which one to use.

My Failed Solution 2

Idea 2 is to go ahead and give them the same exact implementation library... but before giving it to them, remove all of the logic and throw not implemented exceptions.

This works, but it is a lot of work for me, and I have to give the libraries to them manually. So they won't be able to use NuGet or something to pull them.

My Failed Solution 3

Similar to Idea 2; Idea 3 is to create a new NuGet package named CompanyName.ProjectName.________ which is the same as Idea 2 above.

I haven't tried this yet, but I assume it would work. They would implement the library, and when they give me their assemblies, I would just replace their bogus dll with the one I have. Or, in reverse, when they pay for the product, they would just replace their bogus one with the paid one.

One problem here is... I haven't tested this directly, so I'm unsure if it would work. Though, given my knowledge of namespaces and assembly signing, I assume it would be easy to make it work. I can't test it without an acceptable naming convention though, so...

The main problem here is, what would that NuGet package be called? It can't be Core, Implementation, or Empty. Is there already a pattern for this, or do I need to make something up.

My Failed Solution 4

Purchase an obfuscator and implement a licensing scheme such that... un-licensed users would be blocked from accessing the implementation, but could still consume the contracts.

This is expensive and requires the work to implement the licensing scheme... I actually plan to do all of this, but not until the new year. I am hoping there is some other answer that is good to use in the intermediary.

  • Why don't you use interfaces for the contracts instead of abstract classes? Your abstract classes could then inherit from the interfaces, and you get the best of both worlds: the user can substitute the abstract class for the interface if they want the paid functionality. – Robert Harvey May 16 '18 at 17:46
  • That is indeed what I'm doing. Some users do their own implementation with the Interfaces, and there is no problem there. The Abstract Classes do inherit the interfaces, and expose a couple new virtual methods. I'd like for prospective users of my official implementation to be able to see that contract without yet getting the implementation. – Suamere May 16 '18 at 17:55
  • Is the problem those new virtual methods, and not the methods on the interfaces? – Robert Harvey May 16 '18 at 18:11
  • Right, I want them to have access to those. And I do not want to put them into the Interface just for the sake of them being there. The interface is clean and works as it is supposed to for its consumers. The Abstract Classes are special Official Implementations that paying consumers can utilize. – Suamere May 16 '18 at 22:46
  • Then I guess you're going to have to put some sort of security on those abstract methods, so that non-paying customers don't get the features you don't want them to have. – Robert Harvey May 16 '18 at 23:20
1

You should go for a licensing scheme, but in the meantime you could do the following.

In your implementation project define a new build configuration, similar like the out-of-the-box ones DEBUG and RELEASE, pick eg COMMERCIAL. Maintain a build with and without this directive; you hand out the one with the COMMERCIAL directive to paying users.

In the virtual methods of your abstract class you throw if the directive has not been defined, eg.

protected virtual void DoWork()
{
    #if !COMMERCIAL
    throw new Exception(“...”);
    #endif

    // Do actual thing.
 }

To prevent reverse engineering, you invest in an obfusticator.

The pro of this approach is that you don’t have to come up with a licensing scheme yet and that you only have to maintain a single codebase.

  • 3
    Obfuscators don't prevent reverse engineering; they just attempt to make it more difficult. – Robert Harvey May 26 '18 at 18:15
  • 1
    @robert-harvey That’s true, in a literal sense, but it’s the best we have in the .NET world. It is still possible to extract the code, but it will be a hell of a job to make something out of it. – pfx May 26 '18 at 18:22
  • This answer is amazing. I'm sure if I say it is thinking "out of the box", somebody might say, "Psh, that's common in the box I'm from." But it hadn't even crossed my mind. And being that a Build Server can take the build configuration as a parameter, it is easy to have a dummy implementation pushed to NuGet, and a full implementation pushed to my private NuGet. Obfuscation is somewhat a gimmick, but like you say, it's all we've got. So this answer requires the cost of an Obfuscator, but not the cost of implementing licensing yet. Only answer so far, but I like where you're going. – Suamere May 26 '18 at 19:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.