C# solution structure
Project ApiReduced: A class library containing a file Reference.cs generated by a tool. It contains dozens of partial classes, most of which inherit from another .NET class, e.g. the class ODataService inherits from DataServiceContext. The classes are all in the same namespace Som.
Project ApiFull: Class library same as ApiReduced, but contains more partial classes, classes have further properties, etc. Think of it as a superset of ApiReduced. Again, under the same namespace Som.
Project ApiExtensions: Contains Extensions.cs, which should either (not yet decided if inheritance or extension methods make most sense)
inherit from either of the ODataService classes or
provide extension methods for the classes in either project ApiReduced or ApiFull
Project MyProject: Contains code that references either project ApiReduced or ApiFull. Furthermore, it references ApiExtensions.
Desired effect
What I want to accomplish with the above is to be able to decide in MyProject what API to use (full or reduced), depending on whether I add a reference to ApiReduced or ApiFull. In reality I have several projects, some should use the full API, some the reduced API, but I want to be able to use the same extensions in either case to avoid code duplication.
What I've tried
When in ApiExtensions I reference both ApiReduced and ApiFull, I naturally get a lot of errors that the types defined in Reference.cs exists in both libraries. On the other hand, how can I implement Extensions.cs without referencing at least one of ApiReduced or ApiFull? And if I make a choice, that seems rather arbitrary.
TL;DR
How can I swap between using two nearly identical class libraries (in the sense they define partial classes with the same names in same namespace) for my extension methods/derived class?
Short answer: Interfaces and dependency injection!
Any behaviour you want to add an extension to should be based on an interface, and then you implement that interface in both your Full & Reduced api classes. Your extensions assembly should only reference the interfaces assembly and add extensions as appropriate. At this point your assemblies look like
ApiFull (references ApiInterfaces)
ApiReduced (references ApiInterfaces)
ApiExtensions (references ApiInterfaces)
ApiInterfaces
MyProject (references ApiExtensions, ApiInterfaces and either ApiFull or ApiReduced)
Then in your project you again only code against interfaces, and in that way you can use the extensions as necessary. In this project, you use Dependency Injection to inject the correct concrete class (from either ApiFull or ApiReduced)
No answer is complete without a code sample. So, adding extensions to interfaces:
using System;
public class Program
{
public static void Main()
{
var foo = new Foo();
Console.WriteLine(foo.SayHello());
}
}
public static class INamedExtensions
{
public static string SayHello(this INamed named)
{
return $"Hello from {named.Name}";
}
}
public class Foo : INamed
{
public string Name {get => "Foo";}
}
public interface INamed
{
string Name{get;}
}
I suggest you split your Extensions into ApiReducedExtensions and ApiFullExtensions.
That way, when you want to use the Reduced API in a project you include ApiReduced and ApiReducedExtensions
And when you want to use only the FullApi, you only include ApiFull and ApiFullExtensions
Edit
To avoid duplicated code between the two you can add another class ApiSharedExtensions which contains the code both have in common. Same for the Api
Related
We have a server that can return a "configuration", this configuration is a big and complex hierachy of classes.
Our application works by "packages", meaning that we have a "common" base, and then there is part of the application that will not be even installed.
It means that the configurations classes are not all in the same project, and we often have structure like:
public class SomeObject{
public IEnumerable<ISomeObjectChild> Childs{get;set;}
}
public interface SomeObjectChild{
//[...]
}
And in some other project, have some class that implement them:
public class SomeChildImplementation: ISomeObjectChild{
//[...]
}
There is factory to instantiate those kind of childs and everything is working fine.
Now we have to transfer over the network this kind of configuration, using WCF.
My issue is that I know I should indicate what could be the types potentially implementing the ISomeObjectChild. I know that usually, we should declare them with [KnownType(typeof(SomeChildImplementation))], but it is not possible:
This class doesn't know all its possible childs
This class cannot even reference thoses childs
So how could I indicate what are the possible implementations?
(in this case it's with an interface, but I've some others cases with abstract classes).
KnownTypesAttribute has another constructor that can be used to specify a method that will return an array of KnownTypes, see here
The implementation of this method can depend on how dynamic you want to be. Either configure the types you want to support in some configuration file or use System.Reflection to scan for classes that implement ISomeObjectChild
I'm working on a large API project that needs to release 2 DLLs with many interfaces written in C++/CLI (one DLL contains interfaces for public use and the other extends some of the public interfaces for internal company use only).
All implementation classes for all interfaces are in a separate project and are all contained in a separate DLL as well.
Most internal interfaces usually just extend the public version by one by 1 or 2 methods, I opted to reuse the same implementation classes for code reuse.
Here's an example:
//Company.PublicInterfaces.dll
namespace Company
{
namespace PublicInterfaces
{
//contains public properties, methods, etc that any developer can use
public interface class ICompanyProduct
{
void GetProductInfo();
//...etc
}
public interface class IOtherStuff
{
void GetOtherStuff();
}
//...plus many more interface definitions
}
}
//Company.InternalInterfaces.dll
namespace Company
{
namespace InternalInterfaces
{
//extends the public interface to include secret methods that only company developers can use
public interface class ICompanyProductInternal : ICompanyProduct
{
void GetSecretInfo();
//...etc
}
//...plus many more interface definitions
}
}
//Company.InterfaceImplementations.dll
#include "Company.InternalInterfaces.h"
namespace Company
{
namespace InterfaceImplementations
{
public ref class CompanyProductImplementer : ICompanyProduct, ICompanyProductInternal
{
//implements both interfaces
}
public ref class OtherStuffImplementer : IOtherStuff
{
//implement other stuff
}
//...plus many more interface implementations
}
}
//C# Test App
using Company.InternalInterfaces
using Company.PublicInterfaces
using Company.InterfaceImplementations
namespace TestApp
{
class TestAppProgram
{
static void Main()
{
//write code that uses both interfaces for reusability or for whatever reason....
ICompanyProductInternal internalProduct = new CompanyProductImplementer();
IOtherStuff otherStuff = new OtherStuffImplementer();
}
}
}
The Company.InternalInterfaces project references the Company.PublicInterfaces project.
Since we can't ship Company.InternalInterfaces.dll, the Company.InterfacesImplementation project can only reference Company.PublicInterfaces or we risk exposing the internal interfaces.
But since class CompanyProductImplementer also implements ICompanyProductInternal, I had to include "Company.InternaInterfaces.h".
When building the C# test app, Visual Studio 2013 complains of
Error: The type 'Company.InternalInterfacs.ICompanyProduct' exists in both 'Company.InterfacesImplementation.dll' and 'Company.InternalInterfaces.dll'
The only way it works is if the implementation project also references the internal interface project, but that's not possible because I'll have to ship the internal interface library as well.
How can I solve this? Obviously this is a typical scenario with regards to many companies wanting to reuse their code for public and internal use in large projects.
As I see Company.InternalInterfaces.dll and Company.PublicInterfaces.dll are only interface dlls for the same Company.InterfaceImplementations.dll where all logic implemented. Such configuration typically used when you don't need to hide functionality, but because of usability reasons. In this configuration anyone could access Company.InterfaceImplementations.dll code logic via decompilation and execute any code via reflection.
To hide internal logic you could extract Company.Base.dll with common services used by everyone and split other code from Company.InterfaceImplementations.dll into internal Company.Internal.dll and public Company.Public.dll. In such case you need to distribute Company.Base.dll and Company.Internal.dll or Company.Base.dll and Company.Public.dll.
The other option is to create two build configurations PublicAPI and InternalAPI for Company.InterfaceImplementations.dll. In different configurations, different #define directive should be used. In this case code logic could be included or excluded based on this #define. It will give you ability to exclude internal logic from public dlls.
Error: The type 'Company.InternalInterfacs.ICompanyProduct' exists in both 'Company.InterfacesImplementation.dll' and 'Company.InternalInterfaces.dll'
Any way you should split your code properly to prevent duplicate definitions of the same interfaces in several dlls. Place it in only one dll, e.g. Company.Base.dll.
To properly consumes C++-CLI types defined in other assembles you should use using. E.g:
using "Company.InternalInterfaces.dll"
instead of
#include "Company.InternalInterfaces.h"
in your Company.InterfaceImplementations.dll assembly. Useful C++-CLI article "How to: Define and Consume Classes and Structs".
As among many, I have a .NET solution with many projects underneath.
The problem is this:
I use some lines of code repetitively in my project. Its kind of copy-pasting and I really hate that..
My idea is to move all these code in to a separate helper class but the following questions are preventing this idea:
The security aspect --> When I move this code out of my project, this means that somebody can still access it. If it were in my project, I could provide it security by making the concerned function "private".
So, the question is how to avoid code repetition but at the same time doing it securely ?
Some code to explain my concern:
project A (of Solution S)
private Foo SomeSecureCode(IMyInterface interfaceObject)
{
//Same some lines of code
}
project B (of Solution S)
private Foo SomeSecureCode(IMyInterface interfaceObject)
{
//Same some lines of code as above
}
Instead, moving this Function in a helper class but how making it securely?
(Minor details: I am using .NET version 4 with VS 2010)
This could be a solution:
Moven the class from project A to an other project (B) and make the class internal
Sign the projects that want't t use the class with sn.exe and sign the project in the properties of the project.
In project B add this to AssemblyInfo under the Properties folder of project B.
[assembly: InternalsVisibleTo("Full.Assembly.Name.Here, PublicKey="Cut and past the public key of project A here>")]
Now you can use it only in project A and B.
To sign the project:
Run sn.exe
Call the result of Sn.exe sn.key
Add sn.key to your project
Open the properties of the project you wnt to sign (Alt+Enter)
Go to tab "Signing
Check the checkbox "Sign the assembly
Choose the strong name key in the combobox
Compile the project
Now the project is signed you can make internals visible in an other project by adding the InternalsVisibleTo attribute to the AssemblyInfo of the project with the internal class.
maybe this points in right direction:
InternalsVisibleToAttribute: Specifies that types that are ordinarily visible only within the current assembly are visible to a specified assembly.
Could you use inheritance and have the "helper" class be the base of the classes that need it?
sealed class A : C { }
sealed class B : C { }
abstract class C {
protected Foo SomeSecureCode(IMyInterface interfaceObject);
}
You can also use object composition and internal classes.
In one assembly:
class A {
private Helper _helper;
private Foo SomeSecureCode(IMyInterface interfaceObject) {
return _helper.SomeSecureCode(interfaceObject);
}
}
And in a different assembly:
internal class Helper {
public Foo SomeSecureCode(IMyInterface interfaceObject) {
// your code here
}
}
Then use the Assembly InternalsVisibleTo attribute in the assembly containing Helper to allow assemblies that need to see Helper to access it.
Also, keep in mind that anyone using your assembly could access and call your private method(s) using the Reflection API, and tools like dotpeek will let them see your code with only a little bit of information lost.
I am having the following problem. I have a main project, and some extra projects that have similar functionality.
For example: I have an MVC website, then a class library project "A" with a "SettingsHelper". This just defines static wrappers for configuration settings so they can be used as propertys.
Then I have another class library project "B", which also contains a "SettingsHelper class".
How can I merge these SettingsHelpers in my main project, so I can use: SettingsHelper.Property from both modular extra projects.
I would like to be able to plug extra class libraries into one project.
Sounds pretty much like Dependency Injection. Normally you would expose SettingsHelper as an interface (your contract), and program against that. Then a DI container, such as Ninject, StructureMap, or Windsor would plug an implementation of that interface into the relevant parts of your code based on configuration.
This would allow you to code against a known contract and provide different libraries depending on the circumstances, the DI framework could then use that library to get the concrete implementation of the interface.
Would you need both instances at the same time?
Note that you cannot utilise the partial keyword across different assemblies, only within an assembly.
Update: based on your comment it sounds like you want to do something like Composition. Have a class that takes both classes from either library and combines them into one class that can be used by your application. Whether you then configure it to do something special or load the types when the libraries are present, it can all be encapsulated in this new class.
Update 2: alternatively, look into MEF:
http://msdn.microsoft.com/en-us/library/dd460648.aspx
That won't work. Partial classes cannot be divided over assemblies -- they don't exist in the CLR, only in the editor and the compiler. So they are compiled together into a single CLR class.
What you can do, is inherit one from the other. However, helpers tend to be static classes, so that won't work either.
The other alternative is not to write helper classes, but extension methods. You can extend classes in one assembly with methods defined in another assembly (or multiple other assemblies). See also http://msdn.microsoft.com/en-us/library/bb383977.aspx.
I would say that move both Helper classes in 3rd project and add reference of that project to both of your projects. So this new library will become shared datastructures and functionalities library.
Regards.
The specific pattern you are after is called a Facade Pattern. Unfortunately you are not going to get any help from the compiler getting this right. Essentially:
Create a new CombinedSettingsHelper class in your local assembly.
If the two SettingsHelper types are in the same namespace you will need to set up aliases for them (check the reference properties in the solution explorer, and MSDN documentation for this).
Implement the object so that it can access both SettingsHelper objects.
To clean up your facade you might try having a abstract method along the lines of abstract object GetSettingValue(string name);. Your facade could then inherit from the same base class and call these on its contained children. For example:
public abstract class SettingsHelperBase { public object GetSettingValue(string settingName); }
// Assembly1
public class SettingsHelper : SettingsHelperBase { }
// Assembly2
public class SettingsHelper : SettingsHelperBase { }
public class SettingsHelper : SettingsHelperBase
{
private List<SettingsHelperBase> _backends = new List<SettingsHelperBase>();
public readonly PropertiesImpl Properties;
public class PropertiesImpl
{
private SettingsHelper _settingsHelper;
public string Name
{
get
{
return (string)_settingsHelper.GetSettingValue("Name");
}
}
internal PropertiesImpl(SettingsHelper helper)
{
_settingsHelper = helper;
}
}
public SettingsHelper()
{
_backends.Add(asm1::MyNs.SettingsHelper);
_backends.Add(asm2::MyNs.SettingsHelper);
Properties = new PropertiesImpl(this);
}
protected override object GetSettingValue(string settingName)
{
foreach (var item in _backends)
{
var val = item.GetSettingValue(settingName);
if (val != null)
return val;
}
return null;
}
}
There is a way; Visual Studio allows the same code file to be included in more than one project.
When you do “Add”/”Existing Item” to can select a file that is in the different folder.
This is what some of the silver light support does so as to allow a “common class” that has some method that are only on the server and one methods that are only on the client.
(As to the question of “good design” you will have to decide that yourself, a lot of people don’t like having the same class compiled in different ways in different projects. Think if the mess you could get in with #if XXX, when XXX is only defined in one of the projects)
We put all of our unit tests in their own projects. We find that we have to make certain classes public instead of internal just for the unit tests. Is there anyway to avoid having to do this. What are the memory implication by making classes public instead of sealed?
If you're using .NET, the InternalsVisibleTo assembly attribute allows you to create "friend" assemblies. These are specific strongly named assemblies that are allowed to access internal classes and members of the other assembly.
Note, this should be used with discretion as it tightly couples the involved assemblies. A common use for InternalsVisibleTo is for unit testing projects. It's probably not a good choice for use in your actual application assemblies, for the reason stated above.
Example:
[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{
Below are ways to use in .NET Core applications.
Add AssemblyInfo.cs file and add [assembly: InternalsVisibleTo("AssemblytoVisible")]
Add this in .csproj file (the project which contains the Internal classes)
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Test_Project_Name</_Parameter1> <!-- The name of the project that you want the Internal class to be visible To it -->
</AssemblyAttribute>
</ItemGroup>
For more information please follow https://improveandrepeat.com/2019/12/how-to-test-your-internal-classes-in-c/
If it is an internal class then it must not be getting used in isolation. Therefore you shouldn't really be testing it apart from testing some other class that makes use of that object internally.
Just as you shouldn't test private members of a class, you shouldn't be testing internal classes of a DLL. Those classes are implementation details of some publicly accessible class, and therefore should be well exercised through other unit tests.
The idea is that you only want to test the behavior of a class because if you test internal implementation details then your tests will be brittle. You should be able to change the implementation details of any class without breaking all your tests.
If you find that you really need to test that class, then you might want to reexamine why that class is internal in the first place.
for documentation purposes
alternatively you can instantiate internal class by using Type.GetType method
example
//IServiceWrapper is public class which is
//the same assembly with the internal class
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
.CreateInstance(type, new object[1] { /*constructor parameter*/ });
for generic type there are different process as bellow:
var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
.CreateInstance(genType, new object[1] { /*constructor parameter*/});
Classes can be both public AND sealed.
But, don't do that.
You can create a tool to reflect over internal classes, and emit a new class that accesses everything via reflection. MSTest does that.
Edit: I mean, if you don't want to include -any- testing stuff in your original assembly; this also works if the members are private.