Use existing source code in another project/namespace - c#

I have two library projects within a single solution (in addition to other projects) which necessarily need to share certain classes but must remain separate for automatic-update reasons.
For the classes that are shared, I would ideally like to use the same class.cs file in both libraries so that I don't have to consistently check that changes to the class are propagated through both libraries.
However the namespaces of the two libraries are different, and so the class-containing file in each library requires a different namespace classlib {} declaration.
I am using a git repo, if there is a technique to do this through branch/merge operations.
Presently using VS2013.
How can I achieve this?
Example:
library1.dll
namespace library1
{
public class SharedClass
{
/// code must match SharedClass in libary2
}
}
library2.dll
namespace libary2
{
public class SharedClass
{
/// code must match SharedClass in library1
}
}

Declare the SharedClass in a common namespace, instead of two different namespaces. You could link the file into the projects instead of including it physically.
From msdn:
You link to a file from your project in Visual Studio. In Solution Explorer, right-click your project, and then select Add Existing item Or, you can type Shift+Alt+A. In the Add Existing Item dialog box, select the file you want to add, and in the Add drop-down list, click Add As Link.
namespace Khargoosh.MathLib.Common { public class SharedClass { ... } }
namespace Khargoosh.MathLib.Library1 { ... }
namespace Khargoosh.MathLib.Library2 { ... }
or
namespace Khargoosh.MathLib { public class SharedClass { ... } }
namespace Khargoosh.MathLib.Library1 { ... }
namespace Khargoosh.MathLib.Library2 { ... }
A completely other way of handling that would be to use the T4 template with some logic to create the file dynamically. Content of the *.tt template files (not *.cs files!):
namespace library1
{
<## include file="MyCommonClass.cs"#>
}
And in the other library
namespace library2
{
<## include file="MyCommonClass.cs"#>
}
The class file itself would not declare a namespace.

Based on the info you've provided, if your shared classes are truly "common" you should create a 3rd library that both of your main libs can reference. for example:
MainLib1
(reference commonLib)
MainLib2
(reference commonLib)
commonLib
(includes class.cs and other common code)

I need to be able to update the library.dll files separately
Then you should use submodules for this task.
Submodule are different git repositories under the same root.
This way you can manage 2 different project at folder level inside the root repository

Related

How to work with a main project and sub-projects in visual studio using namespace

I'm not familiar with namespaces and can't make it to work in visual studio 2017 community.
I created a solution with a empty project, I added a class file in that project:
namespace MainProject
{
class MainClass
{
//some methods
}
}
then I added a empty project to the solution and also added a class file:
namespace MainProject.SubProject
{
class SubClass
{
MainClass var;
public SubClass()
{
var=new MainClass();
}
}
}
The solution structure is like that:
Solution
|
|__MainProject
| |__MainClass.cs
|
|__SubProject
|__SubClass.cs
But I receive the error: error CS0246: The type or namespace name 'MainClass' could not be found
I don't understand what I'm missing.
You seem to have two problems (unless you've glossed over referencing MainProject from SubProject).
1) Classes are internal by default. For it to be seen by another project, it either needs to be intentionally exposed to that other project or, more commonly, marked as public:
public class MainClass
{
//some methods
}
2) You haven't added a reference to your MainProject project from SubProject, so even if you fix #1, you'll still have a problem.
You can add a reference by right-clicking the SubProject in Solution Explorer, selecting References (or Dependencies if you're working with .NET Core/Standard), selecting Add Reference, and then selecting your MainProject from the Projects list.

C# creating a wrapper namespace?

In C#, how can I import all classes from one namespace into another namespace such that these classes are directly accessible from the second namespace?
I'm essentially attempting to rename a namespace in an externally visible manner.
Since code is worth a thousand words, given a DLL with the following namespace:
// Externally written DLL I have no control over.
namespace A
{
class ClassA {...}
}
I'd like to be able to create another DLL along the lines of:
// My DLL
namespace Wrapper
{
using A;
}
So that I can use it like:
// Final C# program.
using Wrapper;
var a = ClassA();
In python, I could accomplish what I want with import *:
# external.py
class ClassA:
...
# mymodule.py
from external import *
# final_program.py
import mymodule
a = mymodule.ClassA()
Disclaimer
I know this is a terrible idea, but I'm unfortunately being constrained by external requirements. The short version is that I have an external DLL that needs to interface with a proprietary system (EnScript, if you're curious). This proprietary system has restrictions on the naming of namespaces that the external DLL of course violates. Thus, I'm attempting to use the wrapper DLL to expose a namespace that is considered valid.
Related Questions
Talks about using in C# vs wildcard imports in java/python. Does not address issue of accessing from second namespace:
Import all subclasses like Java but in C#
C# equivalent to wildcard imports in Java
Namespaces in C# vs imports in Java and Python
Question about including classes in namespace. Issue was use of separate projects and so not applicable to this question:
How To Include Classes From Another Namespace In Assembly Instead of Writing Them Into A Separate DLL File?
You can't move a type to a different namespace (other than physically moving the code). The .NET type system uses the full namespace to uniquely identify the type.
But you can create an alias to mask the original namespace.
Let's say you have a class MyProject.Foo.Bar.Xyzzy.MyClass, and you are tired of typing MyProject.Foo.bar.Xyzzy. You can add a Using directive at the top of the code file like this:
Using DifferentNamespace = MyProject.Foo.Bar.Xyzzy;
Once you have done this, you can refer to the class with just
var c = new DifferentNamespace.MyClass();
You can even use this to include a different namespace in the current default namespace. This will compile:
namespace Example.Classes
{
class MyClass
{
}
}
namespace Example
{
using Example = Example.Classes;
class Test
{
static void Test1()
{
var c = new Example.MyClass(); //Not Example.Classes.MyClass
}
}
}
But unfortunately you have to leave the alias there; i.e., this won't compile:
namespace Example.Classes
{
class MyClass
{
}
}
namespace Example
{
using Example = Example.Classes;
class Test
{
static void Test1()
{
var c = new MyClass(); //Error
}
}
}

Extension methods in a class library project

I've implemented some extension methods and put those in separate Class Library project.
Imagine I have a simple extension method like this in class library called MD.Utility:
namespace MD.Utility
{
public static class ExtenMethods
{
public static bool IsValidEmailAddress(this string s)
{
Regex regex = new Regex(#"^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$");
return regex.IsMatch(s);
}
}
}
But nowhere in the web app like the App_code folder or the WebFroms code-behind page can I use this extension method. If I do something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MD.Utility;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string email = "Someone#Somewhere.com";
if (email.IsValidEmailAddress())
{
//To do
}
}
}
The compiler doesn't recognize IsValidEmailAddress() and there's even no IntelliSense support.
While if I put my extension method in the App_Code folder, it's usable in another .cs files in the App_code folder or the WebForms code-behind pages.
Did you remember to add a reference to your class library in the web project ?
You will need that. Other than that, your code looks fine, and should work.
If changes are not getting recompiled when you do a solution rebuild, then it could be the type of reference you are using. If the MD.Utility project is in your web project solution, you should make the reference a "Project Reference." That will cause the build to consider that code as a dependency and therefore rebuild it when you change something. If you just include it as a DLL, then the DLL is considered external and the build will not consider it, even if it is in the same solution.
I was able to resolve it by making the extension module public.
This post may be helpful:
Extension methods in referenced assemblies?
In addition to adding the assembly to the references, what fixed it for me was to explicitly adding it to the file "using MD.Utility".
I've found that this can occur if the Assembly Name and Namespace of the consuming project are the same and the Common library has the same Namespace.
Seems that the compiler gets confused. Try changing them.
As noted elsewhere, you need to add the Common library to each consuming project. And the Module containing the Extension(s) in the Common library must be marked Public. Unlike Classes, Public isn't the default scope for Modules. No idea why.

C#.NET Namespace name does not exist in namespace error - only when using is outside local namespace directive - why?

Using .NET 2.0, C#, Windows Forms development, Enterprise Library 3.1.
We have a project namespace (call it Project). We also have several sub-namespaces inside of that project, for example Project.Namespace1, Project.Namespace2, etc.
In one class, we define enums and such to be used with the Enterprise Library Logging block, like this:
namespace Project.Logging
{
public static class Logging
{
public enum LogPriority
{
// enum values here
}
}
}
In another class, I use the enum values so I need to declare a using statement. Same project, so there is no assembly to reference, right?
If I declare the using inside of the local namespace, like this, it works fine:
namespace Project.SomeName
{
using Project.Logging;
// code referencing the Logging enum
}
However, if I put the using statement outside of the local namespace declaration, I get the "type or namespace name 'LogPriority' does not exist in the namespace 'Project.Logging'... Like this:
using Project.Logging;
namespace Project.SomeName
{
// code referencing the Logging.LogPriority.whatever
}
Why is this? Has anyone run across this before?
I have run into similar (though not exactly the same) problems before when using a class that has the same name as its namespace.
Oddly enough it seemed to compile ok on some developers pc's but not on others. In the end we made sure that no namespace contained a class of the same name.
namespace Project.Logging
{
public static class Logging // this is what caused the probems for me
{
}
}
I also had a wired error. I cannot find any namespace which is coming from different assemblies, but begins with executing assembly name.
Finally, I found out that I have set the target framework to .NET framework client profile.
Yes, most likely you have an unusual value set for the "Default Namespace" in your project properties. I would validate the project configuration.
We ran into this issue before and it all went down to ambiguous naming of the namespace and the class name.
When we tried to have our namespace as Services.Web.xxx and also add in a service reference as Services.Web.xxxx and ALSO add a references to an assembly that was named Services.Web.xxx you can only imagine the problems we ran into.
In the end to fix it we simply did a rename to make sure that there was only one instance of the Services prefix
Also you could do the following and create an alias to LogPriority to LogEnum:
using LogEnum= Project.Logging.Logging.LogPriority;
namespace Project.SomeName
{
internal class MyClass
{
public MyClass()
{
LogEnum enum1 = LogEnum.None;
}
}
}
namespace Project.Logging
{
public static class Logging
{
public enum LogPriority
{
None,
Default
}
}
}
It definitely can make a difference if you have usings inside or outside the namespace. There is a good discussion here, and it is likely to be related to your default namespace settings.

warning MSB3391: <DLL> does not contain any types that can be unregistered for COM Interop

I've made a simple C# DLL (that's part of a much larger project) using VS2005. I need to use the DLL in Excel via VBA code so I am using COM Interop on the assembly. I am trying to make the build process automatically generate the necessary TLB file so that I don't need to go to the command line and use regasm after every build.
My problem is that although the DLL compiles and builds fine, it does not generate a TLB file. Instead, the error in the title prints out in the output box.
I've gotten other DLLs to build TLB files by going to the project's properties in VS2005 -> Build -> Output -> Check "Register for COM interop". Also I have [assembly: ComVisible(true)] in the AssemblyInfo.cs.
Here's the summary of the source for the problem DLL and the DLL that it references for a return type:
using System;
using System.IO;
using System.Runtime.InteropServices;
using SymbolTable;
namespace ProblemLibrary
{
public class Foo
{
public Foo(string filename)
{
...
}
// method to read a text file into a SymbolTable
public SymbolTable BuildDataSet(string[] selected)
{
...
}
}
}
Here is a summary of SymbolTable.dll. It holds a return type that ProblemLibrary uses.
using System;
using System.Collections.Generic;
namespace SymbolTable
{
public class SymbolTable
{
readonly Dictionary<SymbolInfoStub, string> _symbols = new Dictionary<SymbolInfoStub, string>();
/*methods that interact with Dictionary snipped*/
}
}
You need to have ctor without any params.
You should have GuidAttribute and ProgIdAttribute around the classes.
Its better to mark the assembly as ComVisible(false) and mark explicitly the classes that need export.
Use interfaces for your classes.
Make sure the you have GuidAttribute in the assembly level.
[Guid("<PUT-GUID-HERE-1>")]
[ComVisible(true)]
interface IFoo
{
void DoFoo();
}
[Guid("<PUT-GUID-HERE-2>")]
[ComVisible(true)]
[ProgId("ProgId.Foo")]
class Foo : IFoo
{
public void DoFoo()
{
}
}
In the AssemblyInfo.cs file, make sure you have the following:
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
UPDATE:
Read: How can I make use of .NET objects from within Excel VBA?
Which links to:
http://richnewman.wordpress.com/2007/04/15/a-beginner%E2%80%99s-guide-to-calling-a-net-library-from-excel/
I saw a similar problem. I got an error like:
warning MSB3391: does not contain any
types that can be unregistered for COM
Interop.
I followed all the rules (ComVisible, etc.) but nothing worked.
Solution: I had to put something in the default constructor so that it would not be optimized away. The moment I had something there, the registration finished with no message and the component was visible in the registry.
Interesting note: a friend of mine managed to register the original DLL with the empty default constructor on his machine (64-bit Windows-7, VS2008-Professional, like mine). However, his REGASM.EXE was:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\regasm.exe
while mine was:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe
So it could be some difference between versions of the .NET framework - maybe the later version is optimizing too much and the REGASM does not account for that.

Categories

Resources