Update for clarification:
I have a project which is exposed as Nuget package. I need it to be public to my solution assemblies but private to who ever will consume my package. Is there a way to accomplish that?
Original question:
A project I'm working on is currently using 2 entities projects and it's written over .Net Standard 2.0 framework:
Contract.csproj
Contract.Internal.csproj
The first is configured to be exposed for consumers using a private Nuget server, while the second is for internal use of my solution projects.
The thing is that both has pretty much the same classes except few that are for my solution internal use only.
Is there a way to merge them to a single project and configure some classes to be exposed in the NuGet package while others are not?
I read on the ExcludeAssets/IncludeAssets tags that can be added to the csproj PackageReference, but the docs and all the examples I saw are referring dependencies and their versions and not the project classes.
Also, if you have other solution, you work with your projects some other way on this one (Or even think that I find myself with that scenario is wrong) I'll be more than happy if you share you thoughts on this.
If you want to expose certain classes from your project while keeping other classes internal, you can use C# access modifiers.
For example, a class prefixed with internal will be only visible inside your project:
internal class Foo { }
A class prefixed with public will be accessible for others:
public class Bar { }
I think Wouter's answer should help resolve your problem. But I want to highlight another approach to a similar problem that may help you or other folks in the future.
Since there is an interface/functionality in Contract.Internal.csproj that is internal but needed in Contract.csproj, as a possible solution, instead of making its interface public, you can restrict it with internal modifier. And in order to access that internal interface in Contract.csproj, you can use this answer.
What you'll have to do, is to grant access of the internals visibility to Contract.csproj by modifying the AssemblyInfo.cs file of the Contract.Internal.csproj the following way:
[assembly: InternalsVisibleTo("Contract.Internal")]
A single package is the wrong approach here because it violates the principle of separation of concerns. Instead, you should have MyPackage that has all the public code and is intended to be consumed by anyone, then for your own internal use have MyPackage.Private that references MyPackage. Your users reference MyPackage, you reference MyPackage.Private, and everything is simple.
Related
Let's say I want to write a library and it should invoke OptionalLibClass.Run() if such method is available. However the assembly is big (like SkiaSharp) so I do not want to include it with my library, in case the end developer only need other features.
I know it's possible to use System.Reflection but you lose the benefit of Intellisense and static typing as well as getting a performance hit (though pretty minor IMO, usually it's not a problem).
Expectation:
Add OptionalLib as a reference. Still it should be optional: user should not have to install OptionalLib if they install MyLib from Nuget for example.
Write the following code in the library:
using OptionalLib; // .NET should be able to see this namespace
// ...
if (OptionalLibAvailable()) // How to implement OptionalLibAvailable?
{
OptionalLibClass.Run() // IntelliSense should be able to show me OptionalLibClass
}
End user (developer) doesn't need to do anything beside referring to OptionalLib if they want to.
Note that there may be multiple optional libs.
Possible Workaround:
While typing the questions, I thought of a few solutions though they are not as simple as I would like:
Make an interface IOptionalRun for example. However, end user has to provide their own implementation.
Following above workaround, add a separate MyLib (without OptionalLib) and MyLib.OptionalLib (with OptionalLib) that provides an IOptionalRun implementation. I think this is the best workaround so far and the closest to my expectation but we still need 2 separate assemblies and the user has to register the interface somehow. This workaround has a problem when there are multiple optional libraries and we want users to have any of their combinations (for example: do A if A is available, B if B is available but C if both A and B are available)
Using dynamic: the worst workaround IMO. Technically a shorter System.Reflection solution but still have all its problem.
EDIT: After reading my question again, turn out a solution will probably be the answer to: how to pack/create a Nuget package for a project that contains OptionalLib but it should not be in the dependency list (and don't pack that dll when packing the Nuget package). OptionalLibAvailable can just be a Reflection call to see if OptionalLib assembly is loaded in the current AppDomain.
Edit the properties of that big assembly reference, in the properties window, there is a property Private Assets, set its value to All, then repack your library, you will find that reference has gone from the .nuspec file.
If you had to expose functionality externally as a DLL but only a subset of functionality (meaning you can't provide a core DLL as it would expose everything) how is best to do this?
At the moment I can't really see any way of doing it that doesn't involve recreating the parts of the core library in a seperate DLL.
You could use internal along with Friend Assemblies. Your API can be a friend of the core library allowing access to internal members.
See here for more details - http://msdn.microsoft.com/en-us/library/0tke9fxk(v=vs.90).aspx
This would allow you to keep your core objects internalised whilst allowing the API access to them.
Note that you will STILL need to supply the core library. There's no way around this unless you use something to merge the .NET assemblies or you compile the code into your API library.
However I think this is a bad idea and you should keep such entities separate. I don't see why there is an issue shipping more than one library thesedays.
FYI - ILMerge will let you merge .NET assemblies, you can get it from here - http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx
Surely by just creating a new project that wraps the core DLL, exposing only the methods you want exposed, each of which is acting more or less as a "pass-through" to the "Same" method in the core?
So if you core is called Core :)
it might have:
public int Foo()
{
//blah
}
public int Bar()
{
/blah
}
and if you want to only expose Foo, then you create a new project which references Core, and looks like this:
using Core;
public class MyApi
{
private Core _coreInstance.... //some way of reaching Core, in other words
public int Foo()
{
return _coreInstance.Foo();
}
}
An advantage of creating a separate assembly here is that you are then treating your core functionality as one concept, and the exposure of it publicly (to a particular purpose or audience) as another. You may very well want to expose "publicly" different functionality at a later stage, but to a different audience - you now have 2 different public APIs required: therefore any notion of what was "public" in your core assembly is now potentially ambiguous.
I think it depends on the aims you follow in hiding the core libraries.
If you don't want to allow your customers to call the code, for example if that may break usage scenarios of your libraries, or may cause undesirable behavior, or whatever to prevent CALLING the code, you can make the protected classes internal, and use InternalsVisibleToAttribute to include the Facade assembly. I would even use one more build configuration if I still needed core classes to be visible in my applications:
#if PUBLIC_BUILD
internal
#else
public
#endif
class ProtectedCoreClass
But of course if you have too many classes, some script should be prepared to change the existing classes, and Visual Studio's new class template should be modified.
But another case is if you want to prevent the source code from being WATCHED by your customers in order to hide some super unique algorithms or something. Then you should look into some code obfuscator. But there is absolutely no way to 100% guarantee the code from being decompiled and analyzed. It's only about the price crackers or competitors pay for it.
But if HIDING the source code is still extremly important, you should probably just host your code on your servers (to make sure the code is physically inaccessible) or in the cloud, and provide a WCF or a web service your exposing assembly will call.
I need to declare an attribute for coverage exclusion in my code, the issue is that i have a project group and i wish to create it somewhere where i can access it from all projects when i need it, right now i have it outside of the namespaces so it would be easier to use, and its declared in each project like:
public class CoverageExcludeAttribute : Attribute
{
}
is there any better way to achieve this goal in a way it could be access anywhere in my project group and declared only once, without having to add its namespace (e.g by using the global namespace) to each file i use the attribute in?
Thank you
While I actually agree with P.Brian.Mackey, I think the only way to do it is exactly as DjKraze said:
Create a new micro-project of type ClassLibrary, add a single .cs file with your Coverage(..) class and ensure that class is inside no namespaces block. Then build it and for each one of the other projects do a Add-Reference to that micro-project you just created.. That way it will surely work, and you will have a handy place to put any further 'common code' to be available everywhere.
However, each project will have to be updated with the reference. This is the minimum requirement - all in all, if you want to use anything instead of copying, it must be referred..
Sorry, almost no other options for such thing!
The other way is to .. ugh, copy. You can easily set up a simple pre-build script that will copy given .cs file to each one of your projects, but "adding" the file to the .csproj's build list is a bit harder, still possible with use of some Ruby or Python or friends...
Hm.. saying that, It may be possible to write a pre-build script to inject a reference to the micro-project automatically.. But I wont know if this is worth doing. Do you have more than 50-100 projects? Else, probably it's not worth..
This only applies to VS2010 and above
If you want some source code defined in each of your projects, but without a project reference, take a look at some of the functionality provided by NuGet, especially Source Code Transformations. These allow the addition of some source code to the project when you add the NuGet package to the project.
You can use Dependency Injection
http://en.wikipedia.org/wiki/Dependency_injection
The most popular are: Microsoft Unity, Ninject, NHibernate, StructureMap, Autofac.
Good luck!
I'm learning C# and coming from a Java world, I was a little confused to see that C# doesn't have a "package private". Most comments I've seen regarding this amount to "You cannot do it; the language wasn't designed this way". I also saw some workarounds that involve internal and partial along with comments that said these workarounds go against the language's design.
Why was C# designed this way? Also, how would I do something like the following: I have a Product class and a ProductInstance class. The only way I want a ProductInstance to be created is via a factory method in the Product class. In Java, I would put ProductInstance in the same package as Product, but make its constructor package private so that only Product would have access to it. This way, anyone who wants to create a ProductInstance can only do so via the factory method in the Product class. How would I accomplish the same thing in C#?
internal is what you are after. It means the member is accessible by any class in the same assembly. There is nothing wrong with using it for this purpose (Product & ProductInstance), and is one of the things for which it was designed. C# chose not to make namespaces significant -- they are used for organization, not to determine what types can see one another, as in java with package private.
partial is nothing at all like internal or package private. It is simply a way to split the implementation of a class into multiple files, with some extensibility options thrown in for good measure.
Packages don't really exist in the same way as they do in Java. Namespaces are used to organize code and prevent naming clashes, but not for access control. Projects/assemblies can be used for access control, but you can't have nested projects/assemblies like you can with packages.
Use internal to hide one project's members from another.
I am designing a WPF application that uses a DLL with maybe 40 public classes. I need these to be public for a variety of reasons including ease of data binding and obfuscation. I would like to allow other people to use only a portion of these classes as an API for my software.
I thought I would create the main library (core.dll) and an API library (coreAPI.dll) with the API DLL to be referenced in a new project. Is there a way to allow coreAPI.dll to expose only a few of the classes that exist in core.dll? It's not so much a security issue as I primarily want to simply hide some of the unwanted classes from the Visual Studio Intellisense.
Again, internal classes for the ones I want to hide is not really an option because I need to data bind some of these classes in WPF and for that, they must be public. Are there any other ways of doing this?
As Damien already mentioned, if the only thing you'd like to do is to hide from Intellisense you can add the following attribute to your hidden classes:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
If the primary issue is Intellisense, then moving these classes into a separate namespace would surely do the trick?
Of course, you could split the classes into two separate assemblies. You may have some issues there with having to expose more classes than you want (because they now live in separate assemblies), which might be resolvable using the InternalsVisibleTo attribute