I want to build a Windows Store class library using source code from a regular .NET Framework class library. Ideally, I do not want to modify the original source code files.
In some of the source code files from the .NET Framework library, static members are used from a class that is defined in both the regular .NET Framework API and the .NET for Windows Store apps API, but where only a subset of the .NET Framework members are available for Windows Store.
One specific example is System.IO.Path, where the GetFullPath method is not available for Windows Store apps.
It is fairly straightforward to incorporate a replacement for this method in my Windows Store class library and have the original source code invoke this method instead. My question is, is there any way I can do this without modifying the original source code file?
So far, I have not been able to figure out a satisfactory solution to this problem, but I have solved it for my Windows Store class library by implementing e.g. the Path.GetFullPath(string) method in another namespace:
namespace WindowsStoreLib.System.IO {
public static class Path {
public static string GetFullPath(string path) { ... }
}
}
and then adding a preprocessor directive in the original files:
#if NETFX_CORE
using Path = WindowsStoreLib.System.IO.Path;
#endif
Is there an alternative solution to this issue that does not require modification of the original source code files?
No, you cannot, simply.
When I'm doing cross-platform stuff I tend to write a utility class that has different implementations (via #if) for different platforms - then my core code just calls the utility class.
I've been doing something like this lately with Entity Framework classes since I needed to add a specific output of 2 fields as 1 and it wiped it out from the designer.cs on every update. However they were not static classes or static methods, but should work with same.
Create a new class file with the name of the class you want to extend and use the partial qualifier.
namespace WindowsStoreLib.System.IO {
public partial static class Path {
public static string GetFullPath(string path) { ... }
}
}
As Marc said, the preprocessor directive seems to be the only solution.
But when I read "static class" and "existing class", the first thing coming to my mind is "extension method". What would happen if you created an extension method for Path in the same namespace where your code is?
namespace MyNamespace.WhereMyCodeIs
{
using System.IO;
public static class ExtensionMethods
{
public static string GetFullPath(this Path pathObject, string path)
{
// Implementation
}
}
}
I am really not sure if this would work out but maybe there is a work around we could find around this.
Related
Say I have these files:
MyCode.cs
namespace MyCodeNamespace
{
public class MyClass
{
//OMITTED
}
internal static class MyExtensions
{
internal static void Foo(this string str)
{
//OMITTED
}
}
}
OtherCode.cs
using MyCodeNamespace;
namespace OtherCodeNamespace
{
//OMITTED
}
The two files are part of the same assembly. Is there any way I can make Foo accessible to MyCode.cs but not to OtherCode.cs? My question is similar to this question:
C# Extension Methods only visible and accessible within one class ("private")
But its accepted answer isn't really what I'm looking for. I want to make an extension method that's only visible to the code I'm working on, and according to the answer to the above question, someone could still access it by adding a "using" statement. Is there a way I can create an extension method that is only visible to my code, and nowhere else, not even by another class in the same assembly?
I ask because the syntax for calling an extension method is handy and would be useful for what I'm working on (otherwise I'd just create a private method instead), but I don't want others to see it and use it from their code in case it doesn't do what they assume it does. And thanks to Visual Studio's intellisense, my extension methods are currently showing up in the list of available methods (along with the option to add the namespace they're in).
There is no such thing as a namespace-limited access modifier in the .NET platform. From the docs
public : Access is not restricted.
protected : Access is limited to the containing class or types derived from the containing class.
Internal : Access is limited to the current assembly.
protected internal: Access is limited to the current assembly or types derived from the containing class.
private : Access is limited to the containing type.
That's all you have to work with. So the answer is no.
Extension methods are just semantic sugar that compile to the same IL as calling the static helpers directly.
MyExtensionMethods.DoSomething(myObject);
myObject.DoSomething();
You cannot restrict it from being called, but you can remove its visibility from Intellisense.
Simply move your extension methods to a different namespace, add a using statement in your MyCode.cs and don't include that namespace in OtherCode.cs
[update]
If you really need to restrict the caller, you could try using reflection to determine and restrict, but this is a bit overkill. Best to simply use a private static helper instead of doing this.
var frame = new System.Diagnostics.StackFrame(1, false);
var method = frame.GetMethod();
var type = method.DeclaringType;
// allow|deny type
I had a similar problem. I did not want the programmer to see my inner extension methods when configuring services in ASP.NET Core.
The solution for me was to add all extension methods to namespace Microsoft.Extensions.DependencyInjection that is used in Startup.cs and the user can see those methods. (As you would always do.)
If I wanted to "hide" something I added the extension method to MyNamespace.Extensions. If the user writes the correct name the helper for add using will show up but by default it won't be listed.
I know this is not a solution but might help someone.
think about similar thing;
c# assembly, friend assembly
will try InternalsVisibleTo;
if your classes is closed maybe will not helpfull but you can try it;
I am new to software development and may be I am asking a very silly question but, I am curious to learn more on this thing.
Is it possible to add an extension method to .Net assembly? I want my extension method to work on every project I am working on. Apart from referencing to my own assembly, is there any other way?
If it is not possible, please explain taking some time.
Thanks in advance :)
There's no way of adding methods to an existing assembly.
There's no other way than creating it in your own assembly and referencing that.
Create a new project as a dll (class library)
Add your extention classes/methods to this dll
Reference this dll in your future projects
In response to your comment, you cannot modify the .net framework, only build your own dll's to include methods you wish to share between projects.
The reason you cannot modify the framework is because the code has been compiled already.
You can create extensible method in class but not possible in your reference dll
please check here extensible class method
Is it possible to add an extension method to .Net assembly?
this itself says that you have to create your own methods to extend .Net assembly which are already deployed. The only way to use is define your own methods and include the namespace in the code where you will use these extenssion methods.
sample. of Extenssion methods.
using system;
namespace myNamespace
{
public static class MyExtMethods
{
public static string Foo(this string bar)
{
return bar+ "Some values added. ";
}
}
}
Uses of Extenssion Method.
using system;
using myNamespace;
namespace myNamespace2
{
public class Program
{
public static void Main(string[] args)
{
string str ="Some Value";
Console.WriteLine(str.Foo());
}
}
}
I'm starting a simple C# console solution via Mono on Mac OS X.
I have a Main.cs file for starters, but I want to create a separate class and be able to access object of that class from my Main.cs file.
How can I access that class from the Main.cs file?
Say my class name was Math.
In my Main.cs file, can I create a new object like so:
Math calculator = new Math()
Without referencing the class in the Main.cs file in any way?
Or, do I have to use some sort of import statement/directive?
You need a using statement if your Main and Math are in different name spaces, otherwise it just works. Below is an example. The using System brings in the library that contains the Console class, but no using is required to use the Math class.
Program.cs:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Math caclulator = new Math();
Console.WriteLine(caclulator.Add(1, 2));
}
}
}
Math.cs:
namespace ConsoleApplication1
{
class Math
{
public int Add(int x, int y)
{
return x + y;
}
}
}
There are two scenarios here. Either this class is in a separate dll (class library project), or under the same project. To reference within the same project not additional work is needed, other than referencing it with the correct namespace (as mentioned in other posts).
In the case of a separate dll, you need to add a refence to the project in the project definition. Most default projects come with a reference to System.dll and other related libraries. It is recommended to name your dll's based on what namespaces are defined within it. If you have classes like Foo.Mathematics.IntMath, Foo.Mathematics.DblMath then I suggest you name it Foo.Mathematics.dll.
When I was where you are, I picked up .NET Framework Essentials from O'Reilly and it had answers to all my questions at the time.
I tried to create a class library that is being used in a winforms application in C#.
In my application I have input from a textbox and through a button click I'm instantiating
my event with one parameter (from the textbox). I tried to create a constructor with
this one parameter - but to no avail. It seems if I just add a class to be existing
project I can do this but not when referencing a class library.
Just wanted to find a way to use a one parameter constructor within a class library
if possible. Please help. (this may not work logically because when I reference the
class library - I am actually going outside the original assembly - but maybe....)
If your new class library is in a separate C# project you need to set a reference to that project from your WinForms app before you can use the class.
Of course I'm trying to read between the lines of your original post. It sounds like you know how to make it work, just not when the class is defined in a seperate project. If I've misunderstood, please give more info.
Not enough site experience to upvote or comment myself yet, but DRapp's answer fixed my problem. Since the original question is a bit vague I thought I'd detail what I was seeing a bit more:
I am writing a metro application in C++ which references a class library created in C#. Creating objects exported from the C# module was working fine, unless their constructors had parameters.
// C# file exported to .winmd class library for use in metro app
namespace A
{
public sealed class B
{
public B(bool bTest)
{}
// Other methods/members...
}
}
// C++ metro app referencing .winmd created from C# above
...
A::B^ spB = ref new A::B(bTest); // Throws an exception
Attempting to create an object of type B from the C# module in C++ would throw an exception, with a somewhat cryptic "WinRT transform error" show in the output log.
To fix this, I was able to do what DRapp suggested and add a default constructor to B:
// C# file exported to .winmd class library for use in metro app
namespace A
{
public sealed class B
{
public B()
{}
public B(bool bTest)
{}
// Other methods/members...
}
}
No more exception. :)
it sounds like you don't have two constructors... (overloaded) for your class such as
public class YourClass
{
public YourClass()
{
}
public YourClass(String OneParameter) // this OVERLOADS the default No parameter one
{
DoWhatever with your OneParameter...
}
}
I have a C# library with the following Namespace/Class:
namespace Helper
{
public static class Util
{
/*static methods*/
}
}
I have referenced said library in a F# project and when I try to call one of the methods I get:
error FS0039: The namespace or module 'Helper' is not defined.
This is an example of the method call not working:
#light
let a = Seq.skip 1000 (Helper.Util.GetPrimes 200000);;
Am I missing something obvious? Using open Helper doesn't work either, and the weird thing is that IntelliSense does work, it lists every method in the Util class.
Also, what is the standard practice for calling functions in some of my files from other files in the same project? I don't wanna create full objects just to access a few functions.
Regarding multiple files, see the first portion of "Using multiple F# source files, and a useful debugging technique", as well as the final portion of "Sneak peeks into the F# project system, part three". The former discusses how top-level code in a file implicitly goes in a module of the same name as the filename, whereas the latter discusses how to order files in the project (since you can only see stuff declared above/before you).
What does your GetPrimes method look like? It work for me...
I have a solution with a C# library including this code:
namespace Scratch
{
public static class Util
{
public static IEnumerable<int> GetNumbers(int upto)
{
int i = 0;
while (i++<upto) yield return i;
}
}
}
And calling it from a F# project that references the C# project like this:
#light
let p = Seq.skip 1000 ( Scratch.Util.GetNumbers 2000000);;