Do Portable Class Libraries handle conditional statements / references? - c#

I have a class library that I am sharing between .Net Framework and Silverlight using two linked projects and the linked-files technique.
I'd like to convert that to a single Portable Class Library, but I have one bit of code that is different between the two. I currently use a conditional compiler statements to separate the implementations of this one file.
#if SILVERLIGHT
...
#else
...
#endif
Will this be honored in the PCL?
Also, the part of code that is NOT silverlight makes reference to a third-party regular .Net class library. The PCL still compiles, but I cannot use it in Silverlight because of this reference. Is there any way to tell the PCL to only include it for the .Net usage?

That pattern implements compile-time portability instead of run-time portability.
If you have tons of Silverlight-specific code, then you don't really have a portable library--you should consider factoring out the Silverlight-specific code to a separate assembly and having that specialized assembly take a dependency on your PCL.
If you have very little Silverlight-specific code, you could consider binding to your Silverlight dependencies dynamically at run-time using reflection. Your PCL can then be used in any context, but will "gracefully upgrade" to Silverlight if Silverlight is present.

Related

C# Adding a reference to a class in another project without referencing the project

I have two projects:
ProjectMain (class library)
LibraryProject (class library)
ProjectMain is a class library that should only be compiled as a singular library, no referenced libraries. I require a static class reference from LibraryProject BUT I don't want the LibraryProject assembly to be compiled together with the ProjectMain assembly.
I've tried 'link references' in visual studio but this is no solution as the library assembly is always compiled with the main assembly.
There are clear standard solutions to this issue but I am severely limited by the existing implementation requirements. Only one DLL can be compiled without any of the dependent assemblies being in the execution folder, GAC, private path, reflection etc.
The exact limitations are as follows:
Assembly executed in a sandbox from a third party provider, it only supports adding a single assembly with no direct references/reflection etc (it's horrible but my hands are tied)
We would like to handle the code organisation as best possible which means following standard best practices, unfortunately, due to the above limitation that's proving difficult.
What I would like to know is if there is a way to reference a class within another project without also compiling/using that referenced classes assembly. Possibly a method where the compiler 'embeds' the referenced class at compile time.
If your sandbox does not allow loading other dlls in AppDomain, load it yourself by embedding it. You can use Costura.Fody for this purpose, it is easy to use/install, just reference it from nuget.
Of course, embedding it in every scenario is madness and often comes with completely obscure bugs, which often solvable only by enabling traces in regedit.
So, in your case I would create two projects:
MyDll.csproj //it is my original project, with perfect code design and etc. Lovely.
MyDll.Sandbox.csproj //this one is the same as MyDll.csproj, except it is compiled with additional Costura.Fody reference, into single dll (every reference is put inside)
This way you just need to maintenance that MyDll and MyDll.Sandbox files are the same.

Wrap namespaces into conditional symbol (#if)

I'm writing a simple library for my program.
I wrote a lot classes, however after everything done I realize that I need to wrap the files with specific namespaces into #if conditional.
for example, I wrote an alternative implementation of System.Numerics under .NET 2.0:
namespace System.Numerics
{
public class Vector2
{
//.. implementation here
}
}
However, it's only apply if USE_ALTERNATIVE is defined, so if I target into equal or greater than .NET 3.5, I only need to remove USE_ALTERNATIVE from compilation symbol
The class should be like this:
#if USE_ALTERNATIVE
namespace System.Numerics
{
public class Vector2
{
//.. implementation here
}
}
#endif
however, writing #if to all classes under my custom implementations is really tedious work.
is it possible to accomplish this with find and replace that available in Visual Studio?
OK. There is actually a really easy way to do this, and it does not require you to actually use any #if conditionals at all.
Instead, simply put all of your shim classes (that's the technical term for what you're doing) in the same class library project. This will put them all in the same .NET assembly.
Then, in the referencing project, have two different build configurations, targeting different versions of .NET. In the list of references for the 2.0 config, include the library. In the 3.5 config, simply leave it out.
EDIT: Another solution you can use that uses #if conditionals is to wrap the using directives in your client program (instead of your shim classes themselves). That way, you only have to include one #if directive inside each client class that uses your library (and I would assume that your entire project only encompasses one namespace, correct?)

.Net and Mono sharing different version of the same assembly in a solution

I am using Ninject IoC assembly - an external assembly for IoC , they support both mono and windows. but to work on mono a different compiled version of the assembly is needed.
I have the following problem:
I have a Domain.Core project that uses Ninject windows version
I have two additional project - Call them For.Mono and For.Windows, they both have reference for the Domain.Core project
The problem is that For Ninject to work on mono we have to compile it with a special compilation symbol.
Now the mono version will not work on windows, how can I have resolve the issue of using both versions in the same solution to have the following:
When I run the For.Mono project only the Mono version of Ninject is used, even if the Domain.Core project is using Ninject in some classes inside it's code and referencing the local to it's score windows version - I would like to override this with the Mono version somehow,
And use the Ninject windows version on the For.Windows project, this issue is trivial as it just works, but the first request I am asked to reference the windows version by the compiler when I use code from the Domain.Core in my For.Mono project. I understand that the compiler is right but how can I resolve this issue of cross-platform support with one code-base
Your question is not exactly clear, but from what I gather: You have shared base classes/interfaces in Domain.Core assembly that your project uses, you also have 2 sets of derived classes/interfaces (For.Windows and For.Mono) that provide platform specific implementation of classes/interfaces from Domain.Core. You want to have both For.XXX referenced from your solution.
I don't see problem with that approach. As long as your code only refers to classes from Domain.Core and instantiation code is wrapped in
if (platform = Platform1)
{
// must be function calls in both branches to avoid JIT-ing references
// to unsupporterd DLL for the other platform.
InstantiatePlatformOneClasses();
}
else
InstantiatePlatformTwoClasses();
there should be no problem at either compile or run-time.
Note: using some DI container will solve the same issues easier since you can simply configure it to pick platform specific implementations a run-time.

Mixing Silverlight-Specific System.Xml.Linq dll with Non-Silverlight System.Xml.Linq dll

I have a Logic layer that references Silverlight's System.Xml.Linq dll and a GUI that is in WPF (hence using the non-Silverlight System.Xml.Linq dll). When I attempt to pass an XElement from GUI project to a method in the Logic project, I am getting (basically) "XElement is not of type XElement" errors. To complicate matter, I am unable to edit the Logic layer project.
The Non-Silverlight DLL is at:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll
THe Silverlight DLL is at:
C:\Program Files (x86)\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.Xml.Linq.dll
I am new to C# but I'm fairly sure my issue is that I am referencing different DLL's to access the System.Xml.Linq namespace. I attempted to replace my non-Silverlight System.Xml.Linq.dll with the Silverlight's System.Xml.Linq.dll, but received assembly errors.
Is there any way to resolve this short of scrapping my WPF GUI project and creating a Silverlight project?
The solution is to have two versions your logic project. One that references the .NET 3.5 libraries and the other references the Silverlight libraries. Both projects share a common set of code files.
Hence you get a build for WPF and a build for Silverlight. If you need to change the code of the logic you can make it once and then rebuild the solution which will create both versions of the library.
By default a Silverlight library project has the Conditional compilation symbol of "SILVERLIGHT" already in place. Hence where your logic code may have to deal with differences between .NET 3.5 and silverlight libraries you can use Conditional compilation to work round them.
Silverlight and WPF use fundamentally different frameworks. They are not compatible. A lot of the fundamental framework is identical between the two, but they are not, in fact, the same thing.
Sharing code in different projects, as suggested above, is likely the best solution, but be careful about the conditional compilation. Often that leads to a lot of complexity. Approaches like a decorator pattern with Dependency Injection might be more appropriate to hide the differences.
Edit: Removed some wrong information about Client Profile vs. Silverlight.
Can you clarify "received assembly errors"? You might be able to reference both by using extern alias, but this is tricky and confusing. In hindsight, perhaps placing this dependency in the API was an error. Alternatively: can you possibly rebuild the logic dll for the target framework?

Can you mix .net languages within a single project?

Can you mix .net languages within a single project? So pre-compiled, I would like to call classes and methods of other source files.
For both web and apps?
In particular I'd be interested in F# and C#.
You can mix languages in a single assembly with ILMerge and MSBuild.
Here is a very good example about it.
Yes, you can, but Visual Studio does not support it directly. What you will do is compile code to netmodules, then combine them into a single assembly. The compilers support the "/target:module" option which generates these netmodules.
You can then use the compilers to reference other netmodules when building, or use Assembly Linker (Al.exe). There's even an msbuild task for it: AL (Assembly Linker) Task.
A full overview is provided on MSDN: How to: Build a Multifile Assembly
CMS mentions an interesting approach, but in reality I would suggest you keep things simple and have different assemblies (projects) for the C# and F# code. There are well documented communication points between C# and F# (such as here and here) - I'd recommend them instead. The differences between C# and F# (especially with F# having a different runtime!) are quite large...
you can specify the language in each assembly project (library DLL) and use several of these in the same solution, but i don't think you can mix languages within the same assembly
You can do it in a web site project versus a compile-first project: http://www.aspnetlibrary.com/articledetails.aspx?article=Use-C-Sharp-and-VB.NET-in-the-same-project. A web site's BuildProvider resolves language elements on-the-fly.
.NET's BuilderProvider still isn't available for non-web site projects so you're out of luck for standard app mixed Intellisense.

Categories