Can't access file from seperate assembly? - c#

I have two projects in my solution. One represents the main project and another one has the name of the first project but adds ".API" at the end, which acts as an assembly for my interfaces.
Since I use an interface for specific classes, I access the interface and not the actual concrete class, this brings a problem when I was to access a file from the main assembly inside a file in the main assembly and that's fine, the problem comes as I need to mention it in the interface file.
Otherwise it wouldn't be accessible as the interface file is our class in this example.
Here is a code example...
namespace App.Classes
{
public class User : IUser
{
public SomeType SomeType { get; set; }
}
}
namespace App.Classes
{
public enum SomeType
{
SpecialType,
GoldType,
SilverType,
Other
}
}
namespace App.API
{
public interface IUser
{
public SomeType SomeType { get; set; }
}
}
The error I am receiving is the type or namespace name 'SomeType' could not be found.
When trying to add
using App to the interface file I receive an error telling me that namespace doesn't exist.
Primary assembly name: App
API assembly name: App.API

If i understand you correctly,
You have referenced your API (App.API), from you main app (App).
You are then trying to call/reference SomeType in your API which actually located back in (App).
Basically this (if it could be done) is called a Circular Reference for which .Net disallows.
Further more
The type or namespace name 'SomeType' could not be found
This error is entirely appropriate, because there is no reference (even check your API project) from the App.API project to App. I know its not there because it cant be done, .Net wont let you. Ergo Circular Reference
You need to make common things common, i.e If your API needs to know about SomeType it has to be placed in your API assembly (or a more common assembly that both App and App.API can reference).
The simple solution is to put SomeType back into App.API (the project, not just the namespace)
namespace App.API.Enums
{
public enum SomeType
{
SpecialType,
GoldType,
SilverType,
Other
}
}
Or to create a 3rd assembly and reference it from both the App and App.Api projects

Related

"Could not load type x from assembly" Exception When Trying to Get Custom Configuration Section

When I attempt to load a custom configuration section I defined, I receive the "Could not load type x from assembly" exception. After looking at several similar questions, none of the answers worked. I confirmed that I was using the correct fully qualified class name, as well as the correct assembly name. The assembly was located in the same folder as the configuration file that declared the corresponding configuration section. Nevertheless, I still received an error. Here is a simplified version of my code:
namespace MyNamespace
{
public class MyClass
{
public MyClassConfigurationSection Configuration { get; set; }
public void LoadConfiguration()
{
Configuration = ConfigurationManager.GetSection("mySection") as MyClassConfigurationSection;
}
public class MyClassConfigurationSection()
{
/* ... /*
}
}
The problem turned out to be nesting the custom configuration section class definition inside of another class definition. Apparently, the configuration manager's loading logic cannot instantiate a nested class, even if it is publicly accessible. Simply moving the custom configuration class out of the outer class and into the containing namespace fixed the issue.

Api Controller get all types that implement an interface

I know how to get all types that implement an interface such as using this code.
However I have not figured out why I can't make this work in my Asp.Net MVC ApiController. I have two projects (apologies for the naming convention. I created a solution from scratch just to make sure that my existing one was not the cause of the error):
.sln
-WebAPI
-ClassLibrary1
-Interface1
-Class1 : Interface1
WebApi has a project reference to ClassLibrary1.
Calling my ApiController it looks at the dlls in the bin directory. It is able to get ClassLibrary1.dll but when it tries to look at which type is assignable from Interface1 it does not find anything.
Code is just a .net mvc project and class library and hosted here
You don't need to find referenced assembly by its path, you can just use the type to get its assembly as below:
internal class Program
{
private static void Main(string[] args)
{
var type = typeof(Interface1);
Assembly loadedAssembly = type.Assembly;
var types = loadedAssembly.GetTypes().Where(c => type.IsAssignableFrom(c));
foreach (var typeFound in types)
{
Console.WriteLine(typeFound.Name);
}
Console.ReadKey();
}
}
Output:
Interface1
Class1
The problem is that you have the assembly ClassLibrary1 loaded twice and therefore ClassLibrary1.Interface1 from the reference is not the same interface as ClassLibrary1.Interface1 from the loaded assembly.
Move Interface1 to its own shared library and reference this shared library in both ClassLibrary1 and WebAPI to solve your problem.
About Assembly.LoadFile, this is fine if you're planning to make a plugin like system. This is not needed if you are referencing the library because then you can just enumerate the types from the already loaded assembly.
In that case you can use:
typeof(Interface1).Assembly.GetTypes().Where(c => typeof(Interface1).IsAssignableFrom(c));
as suggested by Bhushan Firake.

WebServices & Namespace in C#

I have a web service with the namespace as the following:
namespace MyNS
{
class MyObject
{
//Implementation here
}
}
And I published the webservice and try to consume that webservice from the next C# Website.
I assigned the service name to "MyWS".
When I try to write the code
I have to write,
MyWS.MyObject obj = new MyWS.MyObject();
But I want to write
MyWS.MyNS.MyObject obj = new MyWS.MyNS.MyObject();
The problem is there might by MyObject class under other Namespaces. So, I want to identify my classes by NameSpaces.
What should I do to use Namespace in the coding?
I do not believe the original namespace is exposed as part of the WSDL, which is what the generation process uses to create the client end point.
This means there is no way to control what namespace your web service is used as.
However you can control what namespace your client end point uses. When you add the service reference, the bottom of the first page (Titled Add Service Reference, and containing Discovery controls) is a text box titled "Namespace". If you change that field to MyWS.MyNS when adding the service it should allow you to reference it as such.
The problem is there might by MyObject class under other Namespaces. So, I want to identify my classes by NameSpaces.
The compiler will give you an ambiguous reference error if you try to use conflicting object names. You will have to qualify them in that case.
So, if you want to give it a certain alias, just type the name as you want it.
namespace This.Is.My.Favorite.Namespace
{
public class MyObject()
{
//stuff
}
}
namespace MyNS.MyWS
{
class MyObject
{
//Implementation here
}
}

Inaccessibility error : NUnit with console application

I have written a console application in C# /VS2008. In that I have multiple classes declared without specifying any accessibility modifier. Like
Namespace MyNamespace
{
Class MyClass
{
..
}
}
Now I added a new console application for testing purpose. I added reference to NUnit framework dll. And then a reference to my main project dll. But when I try to create an object of MyClass into my TestFixture class, then I get an error like "MyNamespace.MyClass is inaccessible due to its protection level"
Do I need to create my class as public? But what if my project cannot afford it?
The class needs to be public if you want it to be accessible from another assembly:
namespace MyNamespace
{
public class MyClass
{
}
}
If your project cannot afford it you may take a look at [InternalsVisibleTo] attribute.

How is an assembly resolved at design time?

I have an extensibility library (or the start of one), with a UITypeEditor. I'd now like to decorate the property with the EditorAttribute. I don't want to reference the extensibility library, as it does not need to be deployed, so I'm using this:
[Editor("MyProject.Extensibility.MyUIEditor, MyProject.Extensibility, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", typeof (UITypeEditor))]
MySpecialType SpecialType { get; set; }
This doesn't work. The type editor is for use on enums and when I use this, the standard enum drop down is shown. However, if you copy the type editor into the project and use a direct type reference, all works well. I've tried testing my string using Activator.CreateInstance and I've got that to work. The MyProject.Extensibility.dll is copied into just about every where (all the project's bin/debug folders). Is there some special place to put an extensibility dll so .net can resolve the assembly?
Thanks!
Just enter Regedit.exe and create a key just like:
HKLM\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\StackOverflow
It doesn't really matter what the name of the key is, all folder names listed within AssemblyFoldersEx are searched for Assemblies design-time by Visual Studio.
A folder must be added in Regedit using a (Default) entry having the folder path as value. (See sibling keys for example).
It's interesting that all folders present in the AssemblyFoldersEx registry key will automatically also appear when you click "Add New Reference" on a project context menu on the .NET tab.
Another approach would be to add the desired assembly to Global Access Cache (c:\Windows\Assembly)
I just made the following test: On a resource assembly I put the following code:
public class MyEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
{
MessageBox.Show("Works");
return null;
}
}
On the consumer assembly (Windows forms executable assembly) I created a component that derives from Button just like this:
public class MyButton : Button
{
[Editor("AssemblyReferenceCL.MyEditor, AssemblyReferenceCL", typeof(UITypeEditor))]
public String MyProp { get; set; }
}
There's no reference between the two assemblies. Everything worked just fine.

Categories