Create and Using DLL in same Project in c# - c#

I am having a DLL file. With the use of DLL, I have to call the methods and add some more methods in my project. Now, I need to migrate the older DLL to Make that project as a new DLL. I done this But the problem is The C# code is converted to net module it shows two errors. I am not clear about that. kindly help me over it.
DLL Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace mcMath
{
public class mcMathComp
{
private bool bTest = false;
public mcMathComp()
{
// TODO: Add constructor logic here
}
/// <summary>
/// //This is a test method
/// </summary>
public void mcTestMethod()
{ }
public long Add(long val1, long val2)
{
return val1 - val2;
}
/// <summary>
/// //This is a test property
/// </summary>
public bool Extra
{
get
{
return bTest;
}
set
{
bTest = Extra;
}
}
}
}
CS Project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mcMath;
namespace mcClient
{
class Program
{
static void Main(string[] args)
{
mcMathComp cls = new mcMathComp();
long lRes = cls.Add(23, 40);
cls.Extra = false;
Console.WriteLine(lRes.ToString());
Console.ReadKey();
}
}
}
Errors:
Program.cs(5,7): error CS0246: The type or namespace name 'mcMath' could >not be found (are you missing a using directive or an assembly reference?)
Tried Methods:
I will add the reference via Project-> Add Reference.
The using Reference also used.
Put the DLL into the current project debug/release folder

I'm guessing you used to have the code side by side, i.e.
public int Add(int a, int b)
{
return a + b;
}
public void SomeMethod()
{
var result = Add(2,3);
}
This works because the scope (this.) is applied implicitly, and takes you to the Add method on the current instance. However, if you move the method out, the scope is no longer implicit.
You will need one of:
the type name if it is a static method
or a static using if using C# 6
a reference to the instance if it is an instance method
Then you would use one of (respectively):
var result = YourType.Add(2,3); (plus using YourNamespace; at the top)
using static YourNamespace.YourType; at the top
var result = someObj.Add(2,3);
Checking the compiler message, it sounds like you've done something like (line 7):
using YourNamespace.YourType.Add;
which is simply wrong; you don't use using to bring methods into scope - only namespaces and (in C# 6) types.
Likewise, I suspect you have (line 22):
var result = YourNamespace.YourType.Add(x,y);
which is not valid as this is not a static method.

Create and Using DLL in same Project in c#
DLL or Class Library is a separate project that can be part of same solution.
As you already know, adding a reference to that dll/project will make it available in your app project.
However if function Add in dll is in different namespace (which would be normal) u would need to add using clause at the beginning of your class

Related

acquire class name from file path

I have a system that reads through a folder and saves the paths to an array list. this folder contains a bunch of class files ".cs" all of these classes implement an interface called BaseScript.
I am attempting to find the class name so that I can call class methods but you are supposed to be able to add class files to this folder on a regular basis, so I cannot hardcode the objects to be created.
e.g. I have a file called "Manufacturing.cs":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LLS
{
class Manufacturing : BaseScript
{
public void init()
{
Console.WriteLine("Manufacturing...");
}
public void uninit() { }
public void recomp() { }
}
}
It implements "BaseScript":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LLS
{
public interface BaseScript
{
void init();
void uninit();
void recomp();
}
}
I need to be able to use the path: "\Scripts\Manufacturing.cs" to call something like
BaseScript[] s = {new "Manufacturing class name"}
I know there must be some roundabout way of doing this.
how can I find the class name and then create an instance from that class?
If your class is in the same assembly then you can create an instance of the object by using Activator.CreateInstance. I didn't try your code on my side. So casting might not work. Double check this code:
BaseScript s = (BaseScipt)Activator.CreateInstance(null, "Namespace.TestClass");
Edit-I mistakenly though you had dlls and not cs files for some reason.
As others say you are not properly explaining the scenario. But from what I understand you are probably implementing a plugin type of pattern here.
In order to call methods on C# classes you may add later on, you need to iterate through the folder, get the *.cs files, compile them and then using reflection, load the assembly and create an instance of a class you know exists(you should know the fully qualified name of the class beforehand). Finally, you should find the method you want to call and then call it using reflection. Here is some code to get you started:
Microsoft.CSharp.CSharpCodeProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new System.CodeDom.Compiler.CompilerParameters();
parameters.GenerateInMemory = true;
//You should add all referenced assembiles needed for the cs file here
//parameters.ReferencedAssemblies.Add();
var files = new System.IO.DirectoryInfo("Scripts").GetFiles("*.cs");
foreach (System.IO.FileInfo file in files)
{
System.CodeDom.Compiler.CompilerResults result =
provider.CompileAssemblyFromSource(parameters, new[] { System.IO.File.ReadAllText(file.FullName) });
object instance = result.CompiledAssembly.CreateInstance(file.Name);
if (instance is BaseScript)
{
//Do processing on (BaseScript)instance
}
}

Error casting object loaded via createInstance

I have an assembly that contains the class RD_ToBeProcessed which inherits from ToBeProcessed. The classes are in separate assemblies.
I load an object using createInstance and then attempt to cast it with the following code:
private Type tbpType = null;
public ToBeProcessed getToBeProcessedObject(string data)
{
// The data is passed in so that the fields are populated with the
// correct data.
if (tbpType==null){
Assembly assembly =
Assembly.LoadFrom("c:\\project\\RD_ToBeProcessed.dll");
tbpType = assembly.GetType("myNameSpace.RD_ToBeProcessed");
}
Object tbp = Activator.CreateInstance(tbpType,data);
// This line throws an error
return (ToBeProcessed)tbp;
}
This is a repeat of the question
.NET: Unable to cast object to interface it implements but I don't know how to resolve it.
The error thrown is
Unable to cast object of type 'myNameSpace.RD_ToBeProcessed' to type 'myNameSpace.ToBeProcessed'.
The accepted answer indicated that the problem was 2 different versions of the base assembly. But I have used ILSpy and both the ToBeProcessed dlls in the application directory and the one in the same directory as RD_ToBeProcessed report:
ToBeProcessed, Version=1.0.4336.31676, Culture=neutral, PublicKeyToken=null
So I am not sure what I am doing wrong. Should I change ToBeProcessed to be an interface (ItoBeProcessed) that is used in the app and the plugin? Then have a separate assembly that holds the base ToBeProcessed class which would not be referenced by the application at all (just the by plugin)?
EDIT: The problem was resolved by using an interface class. I still don't know what was going wrong but Kol's answer showed that in theory this should have worked correctly the way it was.
The following solution compiles and runs without error:
Assembly #1: ToBeProcessed
Compiled to DLL, which is copied to c:\project and c:\project\test. Refers to System.dll. ToBeProcessed.cs:
using System;
using System.Reflection;
[assembly: AssemblyVersion("1.0.*")]
namespace myNameSpace
{
public class ToBeProcessed
{
protected string data;
public ToBeProcessed() { }
public string Process() { return data.ToUpper(); }
}
}
Assembly #2: RD_ToBeProcessed
Compiled to DLL, which is copied to c:\project. Refers to System.dll and ToBeProcessed.dll. RD_ToBeProcessed.cs:
using System;
using System.Reflection;
[assembly: AssemblyVersion("1.0.*")]
namespace myNameSpace
{
public class RD_ToBeProcessed : ToBeProcessed
{
public RD_ToBeProcessed(string data) { this.data = data; }
}
}
Assembly #3: ToBeProcessedTest
Compiled to EXE, which is copied to c:\project\test. Refers to System.dll and ToBeProcessed.dll. ToBeProcessedTest.cs:
using System;
using System.Reflection;
[assembly: AssemblyVersion("1.0.*")]
namespace myNameSpace
{
class ToBeProcessedTest
{
private Type tbpType = null;
public ToBeProcessed getToBeProcessedObject(string data)
{
if (tbpType == null)
{
Assembly assembly = Assembly.LoadFrom("c:\\project\\RD_ToBeProcessed.dll");
tbpType = assembly.GetType("myNameSpace.RD_ToBeProcessed");
}
Object tbp = Activator.CreateInstance(tbpType, data);
return (ToBeProcessed)tbp;
}
public static void Main()
{
ToBeProcessedTest test = new ToBeProcessedTest();
ToBeProcessed tbp1 = test.getToBeProcessedObject("myData1");
Console.WriteLine(tbp1.Process());
ToBeProcessed tbp2 = test.getToBeProcessedObject("myData2");
Console.WriteLine(tbp2.Process());
Console.ReadKey(true);
}
}
}
Output:
MYDATA1
MYDATA2
some people asked it before
have look to this question in stackoverflow How to get a Static property with Reflection
check this post it explains reflection with examples. like case of inheritance and how to use type.GetMethods (BindingFlags.LookupAll) to get all methods.

Extension methods conflict

Lets say I have 2 extension methods to string, in 2 different namespaces:
namespace test1
{
public static class MyExtensions
{
public static int TestMethod(this String str)
{
return 1;
}
}
}
namespace test2
{
public static class MyExtensions2
{
public static int TestMethod(this String str)
{
return 2;
}
}
}
These methods are just for example, they don't really do anything.
Now lets consider this piece of code:
using System;
using test1;
using test2;
namespace blah {
public static class Blah {
public Blah() {
string a = "test";
int i = a.TestMethod(); //Which one is chosen ?
}
}
}
The Question:
I know that only one of the extension methods will be chosen.
Which one will it be ? and why ?
Edit:
This also bothers me, but not as much because it's a static method in a static class after all:
How can I choose a certain method from a certain namespace ?
Usually I'd use Namespace.ClassNAME.Method() ... But that just beats the whole idea of extension methods. And I don't think you can use Variable.Namespace.Method()
No method will be chosen: the call is ambiguous and will not compile.
Why can't you do Namespace.ClassNAME.Method()? Certainly there is nothing that prevents you from treating extension methods as normal static methods, and in fact this is the only way for you to fix the ambiguity and have the program compile.
I had this exact question so I found this post two years later. However, I think it is important to note that this will only not compile and give the "The call is ambiguous" error if the code calling the duplicate extension methods is not in the same namespace as one of them.
If the OP were to change the namespace of his class Blah to either test1 or test2, then the code compiles, and the extension in the same namespace as the caller is used - even when both namespaces are represented in the usings. So if Blah is in the test1 namespace, "1" is returned, and if Blah is in the test2 namespace, "2" is returned.
I think this is important to add to the above answers, because I think one mainstream use-case is to have extensions in a local class library that references external extension libraries (e.g. devs share a common utility library, but have some local custom extensions that might unwittingly have the same name). By maintaining the custom local extensions in the same namespace as the code that uses them, you can maintain the extension call syntax and not have to revert to treating them as static method calls.
As Jon says, if both of these exist when you do the compilation, the compilation will just fail.
But if only one exists at the time of compilation and a external library later gets updated to add the second, the code you compiled will still continue to use the first one. This is because the compiler interally turns your code into the longhand form of calling namespace.classname.method.
I migrated big solution from .Net 4.7.1 to .Net 4.7.2. We use LINQ in our code, and we use well known and established library with name MoreLinq https://www.nuget.org/packages/morelinq/.
.Net 4.7.1 does not have .ToHashSet() methods. We used .ToHashSet() from MoreLinq library. And in the same class in the same cs-file we have both using System.Linq; and using MoreLinq;.
I retargeted a project to .Net 4.7.2 and the compiler showed The call is ambiguous error as described above. The reason was that .Net 4.7.2 added new extension methods with the same name .ToHashSet().
I cannot reimplement huge code base. I cannot replace MoreLinq with another library. This is what I did. I created a new class in a new file where I have using System.Linq; but not using MoreLinq;. This is the file (ToHashsetHelpers.cs):
using System.Collections.Generic;
using System.Linq;
namespace Common.Helpers
{
/// <summary>
/// This class with only one method helps to resolve
/// name conflict between .Net 4.7.2 and MoreLinq libraries.
///
/// .Net 4.7.2 introduced a new extension method named '.ToHashSet()'.
/// But MoreLinq already has the same method.
///
/// After migrating our solution from .Net 4.7.1 to 4.7.2
/// C# compiler shows "The call is ambiguous" error.
///
/// We cannot have both "using System.Linq;" and "using MoreLinq;" in the same C# file that
/// uses '.ToHashSet()'.
///
/// The solution is to have method with different name in a file like this.
/// </summary>
public static class ToHashsetHelpers
{
/// <summary>
/// The name of this method is ToHashset (not ToHashSet)
/// </summary>
public static HashSet<TSource> ToHashset<TSource>(this IEnumerable<TSource> source)
{
// Calling System.Linq.Enumerable.ToHashSet()
return source.ToHashSet();
}
}
}
And I renamed all .ToHashSet() to .ToHashset() in entire solution.
I was wondering about the same question and I did a quick test inside an asp.net core 6 project.
If you try this, it does not compile. Pretty much similar as other ambiguous calls or statements not involving extension methods.
using TestExtNs;
using TestExtNs2;
namespace YourBlazorProject.Server
{
public class TestMe
{
public void Test() { }
}
}
namespace TestNs
{
public static class Tester
{
public static void RunTest() // Exec this
{
var x = new YourBlazorProject.Server.TestMe();
x.Test();
x.TestExt(); // does not compile !!! error CS0121
TestExtNs.TesterExt.TestExt(x); //explicit call as working alternative
}
}
}
namespace TestExtNs
{
public static class TesterExt
{
public static void TestExt(this YourBlazorProject.Server.TestMe y)
{
Console.WriteLine("ExtNs");
System.Diagnostics.Debug.WriteLine("#> DIAG: ExtNs");
}
}
}
namespace TestExtNs2
{
public static class TesterExt
{
public static void TestExt(this YourBlazorProject.Server.TestMe y)
{
Console.WriteLine("ExtNs2");
System.Diagnostics.Debug.WriteLine("#> DIAG: ExtNs2");
}
}
}
Alternative: If there is an extension method in the same namespace, this 'closer one' is used; otherwise it won't compile.
// SomeTest.cs (example for 'closer namespace')
using TestExtNs; // This is hard REQUIREMENT for bringing the extension method from TestExtNs into scope !!!
namespace YourBlazorProject.Server
{
public class TestMe
{
public void Test() { }
}
}
namespace TestNs
{
public static class Tester
{
public static void RunTest() // Exec this
{
var x = new YourBlazorProject.Server.TestMe();
x.Test();
x.TestExt(); //Ns
TestExt(x); //Ns
TestExtNs.TesterExt.TestExt(x); //ExtNs
}
public static void TestExt(this YourBlazorProject.Server.TestMe y)
{
Console.WriteLine("Ns"); //writes to the Console Window of the *.Server.exe if its out-of-process hosted. if hosted on IISExp then its visbible in if IISExp is launched from console according to stackoverflow.
System.Diagnostics.Debug.WriteLine("#> DIAG: Ns"); //writes to the VS output console
}
}
}
namespace TestExtNs
{
public static class TesterExt
{
public static void TestExt(this YourBlazorProject.Server.TestMe y)
{
Console.WriteLine("ExtNs");
System.Diagnostics.Debug.WriteLine("#> DIAG: ExtNs");
}
}
}
Output:
Ns
Ns
ExtNs

Does the location of the `using` directive make a difference in C#?

I got an error today while trying to do some formatting to existing code. Originally, the code had the using directives declared outside the namespace:
using System.Collections.Generic;
namespace MyNamespace
{
using IntPair = KeyValuePair<int, int>;
}
When I tried to insert the using directive inside the statement (to comply with StyleCop's rules), I got an error at the aliasing directive, and I had to fully qualify it:
namespace MyNamespace
{
using System.Collections.Generic;
//using IntPair = KeyValuePair<int, int>; // Error!
using IntPair = System.Collections.Generic.KeyValuePair<int, int>; // works
}
I wonder what difference there is between the two cases? Does the location of the (import-style) using directive matter?
I used to think that it did not matter, but I always fully qualify using commands.
Edit: Checked the C# spec, section 9.4 says that:
The scope of a using-directive specifically does not include its peer using-directives. Thus, peer using-directives do not affect each other, and the order in which they are written is insignificant.
So if System.Collections.Generic and KeyValuePair are treated as peers then KeyValuePair is going to ignore System.Collections.Generic.
Yes, it does - to a small extent. There is an edge-case to do with scoping / local names, see Eric Lippert's blog.
For a concrete example (specific to alias usage):
using System;
using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("outer"); }
}
namespace MyNamespace {
//using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("inner"); }
}
static class Program {
static void Main() {
Foo.Test();
}
}
}
Yes it does, I have an working example to a similar question (Namespace collisions).
In essence the rules for name lookup are different if the using directive is global (outside the namespace) or inside the namespace when it takes higher precedence.
This is purely informational, re one of the replies claiming it affects the time that the assembly is loaded; but in reality, assemblies are loaded the first time a method/type using them is JITted (or accessed via reflection, etc).
Here's an example showing it making no difference; with the using in either location, the output is the same: System.Core is loaded as Bar gets JITted:
pre-Bar
System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
pre-Max
Max: 5
post-Max
post-Bar
example (run at command line, not in debugger; ideally in release configuration):
using System;
//using System.Linq;
namespace Foo {
using System.Linq;
class Program {
static Program() {
AppDomain.CurrentDomain.AssemblyLoad += (s, a) => {
Console.WriteLine(a.LoadedAssembly.FullName);
};
}
static void Main() {
Console.WriteLine("pre-Bar");
Bar();
Console.WriteLine("post-Bar");
Console.ReadLine();
}
static void Bar() {
Console.WriteLine("pre-Max");
int[] data = { 1, 2, 3, 4, 5 };
Console.WriteLine("Max: " + Enumerable.Max(data));
Console.WriteLine("post-Max");
}
}
}

Namespace collisions

How is it possible that .NET is finding the wrong 'MyType' in this scenario?
I have a type A.B.C.D.MyType in a project that I'm working on, and I'm referencing a DLL that has a type A.B.MyType? I do not have any 'using A.B;' statements anywhere in my code, and I do have 'using A.B.C.D;'. When I compile, the compiler thinks any naked reference to 'MyType' means 'A.B.MyType'.
I know I could just rename the class or use an alias, but I'm wondering how this is even possible.
Any ideas?
Thanks!
Are you working in a namespace that is under A.B namespace? (for example A.B.X) if so the C# namespace resolutions (ECMA-334 C# Language Specification : 10.8 10.8 Namespace and type names) says:
... for each namespace N, starting
with the namespace in which the
namespace-or-typename occurs,
continuing with each enclosing
namespace (if any), and ending with
the global namespace, the following
steps are evaluated until an entity is
located...
and then followed by:
If K is zero and the namespace
declaration contains an
extern-alias-directive or
using-aliasdirective that associates
the name I with an imported namespace
or type, then the
namespace-or-type-name refers to that
namespace or type
This means that name resolution starts at the current namespace and searches all namespaces up to the root, and only after this hierarchical search ends, then the namespaces imported with the using clause are searched.
The following example prints "Ns1.Foo"
using Ns1.Foo.Foo2;
namespace Ns1.Foo
{
class Foo
{
public void Print()
{
System.Console.WriteLine("Ns1.Foo");
}
}
}
namespace Ns1.Foo.Foo2
{
class Foo
{
public void Print()
{
System.Console.WriteLine("Ns1.Foo.Foo2");
}
}
}
namespace Ns1.Foo.Bar
{
class Bar
{
public void Print()
{
new Foo().Print();
}
static void Main()
{
new Bar().Print();
}
}
}
Edit: Adding a using clause inside a namespace, will make so that the namespace is searched before the hierarchical search of current namespace is done is done. Change the example to:
namespace Ns1.Foo.Bar
{
using Ns1.Foo.Foo2;
class Bar
{
public void Print()
{
new Foo().Print();
}
static void Main()
{
new Bar().Print();
}
}
}
and Ns1.Foo.Foo2 will be printed.
Edit: changed example
Is your code in namespace A.B or A.B.C? If so, that's probably the issue. Use a using directive like this:
using TheTypeIWant = A.B.C.D.MyType;
then just refer to TheTypeIWant in your code.
EDIT: I've just tried the "using MyType=A.B.C.D.MyType" option, but that doesn't work. The above is fine though.
Just a guess: in your project properties, is the "default namespace" set to A.B ?

Categories