I have two DLL files that have the same namespace but they have different methods and types.
How can I reference both DLLs in my project and use their methods and types?
By the way, these two DLLs have some methods and types with the same name but different implementation and some unique methods and types.
There's nothing special you need to do - just reference them and use the types. Namespaces can span accross several assemblies without problems, because they're not really opaque types. A namespace is just a way of adding a common prefix to all the types it contains, allowing you to have multiple types of the same name under different namespaces. (The framework doesn't see them as having the same names, because it sees the "fully qualified" name of everything - which has an alias and a namespace attached to the front of it.)
In the rare event that you reference 2 assemblies which have the same type names and the same namespaces (such as 2 different versions of the same dll) - you can distinguish which assembly to use for a given type using an alias. The default alias for all references is global, but you can specify your own alias for any assembly when you reference it (using a compiler switch - or just use the properties box in Visual Studio) - and have an extern alias <name> clause at the top of your code file where you use it - you would access the types from different assemblies with <name>::MyNamespace.Type
If you have 2 types with the exact same name (note that the name includes the namespace) but in different DLLs and you are interested in using both of them, then you can do this.
Short Answer
You have type Acme.Foo in 2 different DLLs and you want to use them. Give the reference an alias in the reference properties window (View | Properties Window) then use it like this:
extern alias TheAliasYouGaveTheReference
TheAliasYouGaveTheReference::Acme.Foo f = new
TheAliasYouGaveTheReference::Acme.Foo();
The default namespace is global for any C# program but note above we are using the alias we created instead of global.
The best approach is to NOT get into a situation like this in the first place, if both assemblies are your own, then do not create 2 types with the exact same name in the exact same namespace. But sometimes we do not control the source code so for those times, the above solution can be used.
Long Answer
I am copying most of the article from here so it is recorded here in case the article is no longer available.
How do you get into a situation like this?
Firstly, here is how you can replicate the scenario so it is really clear what we are talking about:
Create a C# Class Library called FooVersion1
Replace the template code in Class1.cs with the following:
using System;
namespace Acme
{
public class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
Right-click on the solution in solution explorer and select Add | New Project
Save the current project (only applicable in express)
Select a Class Library in the new project dialog and change the project name to FooVersion2 and press OK
Replace the code in Class1.cs with the following:
using System;
namespace Acme
{
public class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
public void Goo()
{
Console.WriteLine("Goo");
}
}
}
Usage of the type in Application
Ok so now we have 2 different assemblies containing Acme.Foo. Let's now create a console application and try to use each one.
Right-click on the solution in solution explorer and select Add | New Project
Select a Console Application and call it Consumer
Right-click on Consumer and select ‘Set as startup project’
Right-click on the references node in the Consumer project and select ‘Add Reference’
Click on the projects tab, and multi-select FooVersion1 and FooVersion2
Click OK
Add the following line to Main in the Program type of the Consumer project:
Acme.Foo f = new Acme.Foo();
Build the solution via Ctrl+Shift+B (or F6)
Notice that you get two build errors [as shown below]:
The Fix
Here is how we can fix it:
Open solution explorer and select FooVersion1 in the References folder of the Consumer project
Hit F4 (or select View | Properties Window)
Change the Aliases property to FooVersion1
Build the solution
Now everything will build correctly, because Acme.Foo unambiguously refers to FooVersion2
Add the following directive to the top of Program.cs in the Consumer project:
extern alias FooVersion1;
Change the usage of Acme.Foo to:
FooVersion1::Acme.Foo f = new FooVersion1::Acme.Foo();
f.Bar();
Notice that when you type ‘f.’ the completion list contains only those methods in FooVersion1 of Acme.Foo (notably it does not include Goo)
Build the solution and everything will build correctly
Finally add the following code under f.Bar() in Program.cs of the Consumer project:
Acme.Foo f2 = new Acme.Foo();
f2.Goo();
Notice that f2’s completion list contains Goo.
Build again using Ctrl+Shift+B and notice that there are still no build errors
you can use the alias feature of the /reference (Import Metadata) (C# Compiler Options) compiler option to solve your problems, read from here for more details
Related
I've a solution with a project named Shared and another project named Foo1.
In Foo1 I've created a folder also named Shared so I've two namespaces named Shared in the solution.
I've added a reference of the project Shared in the project Foo1
But now when I type using in a file in Foo1 IntelliSense don't show the Shared namespaces.
How can I specify in a file that I want to use the Shared namespace from Shared project in Foo1?
Note: The file where I want to use the Share namespace is in the root of the project (I mean outside the Shared folder)
Given the following solution structure:
Solution1
---Shared (project)
---Foo1 (project
--- ===Shared (namespace/directory)
My understanding is that you want to reference something in the Foo1.Shared namespace from within a file living in the root of Foo1, presumably in the Foo1 namespace.
If this is all correct, you could explicitly reference each of your two Shared namespaces using aliases, like this:
using SolutionWideShared = Shared;
using Foo1Shared = Foo1.Shared;
You can now reference any class in either namespace using the alias, like so:
var blah = new SolutionWideShared.SomeClassInTheSharedProject();
or
var bling = new Foo1Shared.SomeClassInFoo1ProjectInSharedNamespace();
This is just one solution, but I'm a fan of explicit code, and this will make for some very readable, non-confusing code.
Ideally, you should rethink your naming, and try to be more descriptive. What is "Shared"? How is it different from Foo.Shared? In production quality code, this would call for refactoring and renaming, IMO. If this is just a dummy play project that you are using to prove some point or play around with some code - then use aliases.
using FooShared = Foo.Shared;
So you will have Shared , which is your initial shared project, and FooShared.
I have a class let's say it's called "Apples". Let's say that class is in a .cs file in a folder called "Apples"
Project
-Apples
-Apples.cs
-main.cs
How can i reference it without writing this:
Main.cs
Apples.Apples.testVar = 2;
and just write
Main.cs:
Apples.testVar = 2;
Is there a way to do this, or will i have to put up with it or change the folder name?
put this at the top of your file -
using Apples = Apples.Apples;
If you have a folder in visual studio and create a class in it, Visual Studio (and possibly other IDEs) will automatically append the folder's name to the namespace of any file created from that folder.
That DOES NOT mean in any way that the namespace has to stay that way. The "folder" is purely for organizational purposes and plays no part in the compilation of your code. The filename doesn't matter to the actual code either. If you look in your Apples.cs just change:
namespace Apples.Apples
{
//....
to
namespace Apples
{
//...
It's simply the rule that your IDE is using as an assumption to what you want. You're not required to follow it.
EDIT: At least that's what I assume to be the misunderstanding here as you're focusing on the folder name - which means nothing to the code and only matters to you. Additionally as previously mentioned you might be hung up on ambiguity between namespace name and class name. As mentioned in other answers it's a bad idea to name a class the same as it's namespace.
By default the global namespace for your project will be the same name as your project. So if you named your project "Apples" and then made a folder called "Apples" and created a class within that folder called "Apples" - You'd then navigate to your class by following the chain of namespaces:
Apples.Apples.Apples
You're drawing the conclusion that you have to do this based on the folder/file names but it's really the namespaces/classes. You have several options here but the bottom line is in order to remove confusion and mess 2 or all 3 of those "Apples" need to change. Changing the file name or folder name will not work. you have to change the class name and at least one of the namespace names. Something more appropriate:
AppleProject.Apples.AppleBase
or even as simple as:
Apples.Apple // removed the extra namespace in the middle
You could alias "Apples" in your using statements:
using Apples = Apples.Apples.testVar;
Or whatever you'd like to make it easier to read.
Yes if you are using C# you just add it in the using references up top of your code file you are on:
EG:
using Apples.Apples;
You just need to ensure you have the reference to the project set if it is not in your current project.
I have an ASP.net MVC 3 project with resource files setup in folders like:
/Resources/EntityName/Views/
/Resources/EntityName/Models/
This means the namespace to access the strongly typed resource values is:
Resources.EntityName.Models.ModelA.Property1
Visual studio gives a compile time error if I try to include the namespace "resources.xxx" and it won't allow the using alias syntax either.
Is there anyway to include or atleast alias the strongly typed namespace of a resource file like it was a normal namespace?
There should be no reason why you can't use one of these objects within a class:
using YourProject.Resources.EntityName.Models;
You might try something like this (not tested, just an idea)
public class myModelA : Resources.EntityName.Models.ModelA
{ /*Leave empty here, nothing to do*/ }
Then you may be able to call the shortest myModelA instead of the complete, verbose name of the resource. Watch out because you'll not be able to access private members of your original model if you inherit it like thi.
I have a basic question.
1-
I want to use Science.dll provided at
http://www.sciencecode.com/
I want to add some new functions in some XXX.cs files and also some new YYY.cs files. Then I want to make dll of them again (Science.dll with changes) and use it. How it can be done.
Should I make a new project and add all more than 100 files (already given on website) in that project and some my new YYY.cs files and then what should be next step???
2-
I wanna ask about best way to put many different functions in one 'utilities.cs' file. Say I have different static functions *printmatrix, read_text_file,* etc. What should I do, so that I directly use them in main program. What should be the way in c#.In c++ I wrote header file and cpp file named utilities and then I used these functions.
Any good idea.
You cannot modify an existing assembly unless you have the source code of it. What you could do is create a new class library project in Visual Studio, add Science.dll as a reference and then add your own functions which could use functions in the referenced assembly. When you compile your project it will produce another assembly.
First you make a new project taht has reference on the science.dll.in Visual studio
You can inheritance its class and add yours functionality.
You can use partial class that has the same name as in the science.dll. and add your functionality
eg:
science.dll
public class Calc
{
public Int32 Add(Int32 a, Int32 b){..implementation...}
}
yourproject.dll
public partial class Calc
{
public Int32 Minus(Int32 a, Int32 b) {..implementation..}
}
You can use extension method with your functionality. This is depend on your implementation.
For detail implementation you can see on MSDN : http://msdn.microsoft.com/library for both C# and VB.NET on both syntak
In the caller project, make sure add reference both science.dll and yourproject.dll.
Let's say I have an application with two files.
Console.cs and Business.cs
Console.cs has program Main class.
Business.cs has three classes named Customer, Order and Orderline.
Is there anyway in C# to determine at runtime (maybe with reflection) that the business objects are in a file named Business.cs?
The C# compiler does not emit this information into the DLL, so it's not available through reflection. However, as you'll be aware from debugging, the debugger can match up compiled locations to source code locations. It does this through PDB files. So it might be theoertically possible for you to ship your PDB files, and invoke the unmanaged debugger or diagnostic symbol store API (see General Reference > Unmanaged API Reference in MSDN) to determine where a given method was defined. You can't really do this for a class, though, because a class could be spread across multiple files using partial classes.
If you compile in debug mode you can probably use Cecil (part of Mono project) to extract the source filenames from the debug symbols. But when you compile in release mode this information probably gets lost.
However, if you need to do this, for other purposes than for example static analysis of your software, you are probably on the wrong track and should think of another solution.
If you put the classes in a Business namespace you could use reflection to find if an object comes from that namespace:
namespace Business {
class Customer {}
class Order {}
class OrderLine {}
}
var myObject = new Customer();
Console.WriteLine(myObject.GetType().Namespace); // writes "Business"
I believe the closest you'll get is typeof(Customer).Assembly.Location. However, this will only give you the DLL, not the location of the source code (which makes sense, since the source code would normally not be included with the binaries).
*.PDB (debug info files) files should have that information. Otherwise I see no way to get it, since code files is just an abstraction which compiled code should not care about.
not sure what your use case is, however if some one is calling you then you can add
compiler directives
[CallerFilePath] string file = "", [CallerLineNumber] int LineNo = 0
in your method.
if not than your best way of accessing this is by using the .pdb file that get's generated. The format is published and a C++ dll is available that can be used to access the file however the easiest way to read the file (and possible line number) if included in the pdb file is using stacktrace
You can access the stack in an exception, so if a class allows you to throw an exception by passing null where you should not than try catch it and you have your stack trace.
if you need the calling file but do not want to add the compiler directives as some one can simply overwrite it you can do something like:
StackTrace st = new StackTrace(new StackFrame(1));
st.GetFrame(1).GetFileName());
Assuming :
You have a project (probably technical with some extension methods etc) that all other projects in your solution reference (let's name it "NameSpaceGloballyVisibleByAllProjects")
You are using SDK-style csproj for your project (otherwise you'll have a little more work)
People in your team code without doing fancy things (ie: "class" / "struct"/ "enum" keywords are at the beginning of their own line in your .cs files).
It means that, by adding this class in "NameSpaceGloballyVisibleByAllProjects":
using System;
using System.Runtime.CompilerServices;
namespace NameSpaceGloballyVisibleByAllProjects
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true, Inherited = false)]
public class MemorizeFilePathAttribute : Attribute
{
public string Path() { return _filepath; }
public MemorizeFilePathAttribute([CallerFilePath] string filepath = "")
{
_filepath = filepath;
}
readonly string _filepath;
}
}
You can simply use it like this:
using System.Reflection;
using NameSpaceGloballyVisibleByAllProjects;
Type type = typeof(Program);
var files = type.GetCustomAttributes<MemorizeFilePathAttribute>(false).Select(att => att.Path).ToList();
Note: As you notice there are more than one file! This is because of "partial" keyword in C#. So it's up to you to use "files.Single()" or not...
We just need to add this attribute above all types now
We can do that in Visual Studio with Ctr-H (Find-and-Replace).
Select All Solution
Check options "regex" & "case sensitive"
Find: "^( *)([a-z][a-z ]*)? (class|struct|enum) "
(without double quotes, but with the final ' '!)
Replace by: "$1 [NameSpaceGloballyVisibleByAllProjects.MemorizeFilePath]\r\n$1$2 $3 "
(without double quotes, but with the final ' '!)
Be ready for this to take a little time (Go get a coffe... or tea)