I have a common project called common. Inside is a class called ExtensionMethods which is used by legacy applications. I want to break apart the class into multiple files, but keep the name the same. So instead of public static class ExtensionMethods {} I have many public static partial class ExtensionMethods {}.
When I drop the new dll created from the partial classes, I am getting a Method not found: exception by one of the legacy applications using the dll. What is causing this? Is the filename infomation embedded in the dll somehow? Do partial classes make the old and new dll incompatible? What's the deal? The dll is not versioned, and we are not using the gac. It's just a simple dll placed in the same directory as the exe.
Update:
Thank you everyone for the suggestions so far. Here's what I've checked so far
same namespace: check.
same signatures: check.
still public: check.
I can build the legacy app and it builds without error.
Yes, the exception tells me what method it is. Method not found:
'System.Collections.Generic.IEnumerable\`1<!!0> CompanyName.Common.ExtentionMethods.Distinct(System.Collections.Generic.IEnumerable\`1<!!0>, System.Func\`3<!!0,!!0,Boolean>)'.
(Sadly, the misspelling of 'Extension' is the way it is in the code.)
I will begin using some tools suggested by you all to look further.
Answer: User error. The dll I thought I copied wasn't the new dll I thought I was building. I can't figure if it was a rebuild that was needed or a source control problem or just my mistake. Anyways, both answers below were correct, partial classes wasn't the problem, and both answers were helpful, but in the end, I think it was the reflector solution that lead me to finding the problem. Thanks everyone.
Partial classes are a compiler trick, nothing more - there's no meaningful difference in the final assembly.
So, I think that your actual problem lies elsewhere.
Check the details of the exception you're getting and review the source for that particular method.
Also, grab an inspection tool like Reflector or dotPeek to search for the class/method in the assembly itself and you should find the problem fairly quickly.
Assuming all the classes are declared in the same namespace, it should be absolutely fine. Check:
That the classes are all in the same namespace (so you've only got one class with that name in the resulting assembly, rather than multiple classes in different namespaces)
That your method signatures are exactly as they were before - the parameter types, method names etc can't change
That the methods are still public
What happens if you try to build the legacy application against your new DLL? That should show the method being missing at compile-time, which should give you a hint about where you're going wrong. Mind you, presumably the "Method not found" exception should tell you which method isn't being found anyway...
Related
In my .NET solution, I have two projects: one main project and a project for running tests against the main project. In my project, I have several methods that I'd like to keep "private", but would also like to run tests for. Is there an access method that could limit these functions to just inside of my solution?
You are looking for the InternalsVisibleTo attribute.
This attributes lets you specify other assemblies that should have access to types and methods that are internal to your assembly. So, in your main project AssemblyInfo.cs file (or any other source file), you can specify that your test project is a 'friend assembly' and should have access to the internals of your main project:
[assembly:InternalsVisibleTo("MainProject.Tests")]
On a side note, as pointed out by Alexei, if your MainProject is signed with a strong name key, any 'friend' assembly must also be signed. This is explained here
Although, as mentioned in another comment. Best practice is to test your assembly by using its public API.
You can use InternalsVisibleTo attribute to make internal types and methods visible to selected assemblies.
However, you should try to design your API so that it can be tested using only the public interface.
You should seriously think back about the architecture of your solution. This is a smell that often shows that your class does too much things at once.
A simple fix is to extract this responsibility (those private methods) to another class where they then become public and are testable out of the box...
No, there is no way to limit access to "just solution".
The reason is solution is simply group of projects. One project can be in any number of solutions. So even if you "limit" access to projects included in one solution you/someone else can create another solution that somehow will need to magically get access to methods.
Additionally built assembly does not include any information on what solution it was part of - so there is no information at run time to check access.
To you particular problem - InternalsVisibleTo (as shown in other answers) will give access to internal methods to projects you allow (requires strongly signed assemblies) or refactor your code to avoid need for testing private methods.
I'm writing a library that has a bunch of classes in it which are intended to be used by multiple frontends (some frontends share the same classes). For each frontend, I am keeping a hand edited list of which classes (of a particular namespace) it uses. If the frontend tries to use a class that is not in this list, there will be runtime errors. My goal is to move these errors to compile time.
If any of you are curious, these are 'mapped' nhibernate classes. I'm trying to restrict which frontend can use what so that there is less spin up time, and just for my own sanity. There's going to be hundreds of these things eventually, and it will be really nice if there's a list somewhere that tells me which frontends use what that I'm forced to maintain. I can't seem to get away with making subclasses to be used by each frontend and I can't use any wrapper classes... just take that as a given please!
Ideally, I want visual studio to underline red the offending classes if someone dares to try and use them, with a nice custom error in the errors window. I also want them GONE from the intellisense windows. Is it possible to customize a project to do these things?
I'm also open to using a pre-build program to analyze the code for these sorts of things, although this would not be as nice. Does anyone know of tools that do this?
Thanks
Isaac
Let's say that you have a set of classes F. You want these classes to be visible only to a certain assembly A. Then you segregate these classes in F into a separate assembly and mark them as internal and set the InternalsVisibleTo on that assembly to true for this certain assembly A.
If you try to use these classes from any assembly A' that is not marked as InternalsVisibleTo from the assembly containing F, then you will get a compile-time error if you try to use any class from F in A'.
I also want them GONE from the intellisense windows. Is it possible to customize a project to do these things?
That happens with the solution I presented above as well. They are internal to the assembly containing F and not visible from any assembly A' not marked as InternalsVisibleTo in the assembly containing F.
However, I generally find that InternalsVisibleTo is a code smell (not always, just often).
You should club your classes into separate dlls / projects and only provide access to those dlls to front end projects that are 'appropriate' for it. This should be simple if your front-end and the group of classes it may use are logically related.
If not then I would say some thing smells fishy - probably your class design / approach needs a revisit.
I think you'll want to take a look at the ObsoleteAttribute: http://msdn.microsoft.com/en-us/library/system.obsoleteattribute%28v=VS.100%29.aspx
I believe you can set IsError to true and it will issue an error on build time.
(not positive though)
As for the intellisense you can use EditorBrowseableAttribute: http://msdn.microsoft.com/en-us/library/system.componentmodel.editorbrowsableattribute.aspx Or at least that is what seems to get decorated when I add a service reference and cannot see the members.
In the fragment below, the CodeBase property fails on the assembly System.Xml.Xsl.CompiledQuery, no where else. The message says that "The invoked member is not supported in a dynamic assembly".
I get that the CodeBase property is not implemented, what I don't get is why all of a sudden this is a problem. This code has been in service for months without a problem and suddenly ...
if( CompareCaseInsensitive( Path.GetFileNameWithoutExtension( assembly.CodeBase ), namespaceURI ) )
return assembly;
I have several options available to code around this, but I'm hoping that someone can explain what happened in a way that might lead to a more robust solution.
Edited with a follow on question.
Is there some way to tell which assemblies have this property implemented and which do not without resorting to exceptions?
Any code that's generated with System.Reflection.Emit namespace classes won't have a CodeBase. Since the code wasn't loaded from an assembly, it was generated at runtime. That certainly includes System.Xml.Xsl classes, they do use the internal System.Xml.Xsl.XmlILGenerator class which heavily leans on System.Xml.Xsl.IlGen. Lots of Reflection.Emit code there.
I cannot guess why this worked before. Maybe .NET 4.0, not sure.
I am trying to share a common namespace between two projects in a single solution. The projects are "Blueprint" and "Repositories". Blueprint contains Interfaces for the entire application and serves as a reference for the application structure.
In the Blueprint project, I have an interface with the following declaration:
namespace Application.Repositories{
public interface IRepository{
IEntity Get(Guid id);
}
}
In the Repositories project I have a class the following class:
namespace Application.Repositories{
public class STDRepository: IRepository
{
STD Get(Guid id){
return new SkankyExGirlfriendDataContext()
.FirstOrDefault<STD>(x=>x.DiseaseId == id);
}
}
}
However, this does not work. The Repositories project has a reference to the Blueprint project. I receive a VS error: "The type or namespace name 'IRepository' could not be found (are you missing a using directive or an assembly reference?) - Normally, this is easy to fix but adding a using statement doesn't make sense since they have the same namespace. I tried it anyway and it didn't work. The reference has been added, and without the line of code referencing that interface, both projects compile successfully. I am lost here. I have searched all over and have found nothing, so I am assuming that there is something fundamentally wrong with what I'm doing ... but I don't know what it is. So, I would appreciate some explanation or guidance as to how to fix this problem. I hope you guys can help.
Note: The reason I want to do it this way and keep the interfaces under the same namespace is because I want a solid project to keep all the interfaces in, in order to have a reference for the full architecture of the application. I have considered work arounds, such as putting all of the interfaces in the Blueprint.Application namespace instead of the application namespace. However, that would require me to write the using statement on virtually every page in the application...and my fingers get tired. Thanks again guys...
This is possible.
For example, mscorlib.dll and System.dll are two different C# projects that both define classes in the System namespace. (among others)
This error would happen if the Repositories project doesn't reference Blueprint.
Alright - So, I marked SLaks as right because his answer was correct and will probably be the solution for any one else viewing this in the future. My problem had to do with the other 6 project files in my solution. I unloaded them and rebuilt the solution with only the two posted instances and suddenly my Intellisense started working. Even though these two projects had no errors, the errors in other projects were causing some problem in the compile. Damn... Thanks guys.
For what you are trying to archieve, you can also try to put everything into one assembly and declare all classes as internal instead of public. This way the program that uses it will only see the interfaces. You will have to create a set of factory classes that create instances of specific interfaces depending on some parameters. This is really the way to go, because the small assemblies cause a lot of overhead. See the Microsoft Performance Guidelines.
I've got a bit of a conundrum on my hands.
I'm currently compiling a load of 'code snippets' into reusable libraries that I obviously intend to use in multiple applications.
I'm having trouble deciding on an appropriate namespace and assembly name.
Basically, I've currently got JasonSummers.Validation as an example for my validation library, since I have no 'company' and no specific project which the code applies to.
However, later on, when I come to use said namespace in a client's project, I don't think it's really appropriate to have my name referenced in code which they will probably own the IPR for.
I would just use 'Validation' as the namespace (after all, StructureMap is StructureMap, not JeremyMiller.StructureMap) but this may cause confusion for future developers as 'Validation' is used in the 'System' set of namespaces provided by .net
All comments greatly appreciated.
You can always use name from biology e.g Tribulus. or any other for your root namespace. So your code goes into e.g Tribulus.Validation or Tribulus.Utilities etc. Toplevel namespace need not to be a functional name. It can be just a signature of a company or just a unique interesting name as i mention.
In my personal experience, I maintain a code base for that useful functions at source level, i.e., I copy every function I need in every project, under my client brand and assembly name.
I didn't found be useful to keep that functions at assembly level, exactly because that: it'll contain some names which can generate confusion and for an extra reason: a client paid for some functionality, but not for another (include in a general assembly). So, I just pack what he/she bought.
An option could be to use a neutral name, like Reusable and to merge your utility assembly by using ilmerge framework command.
Take a look at Microsoft's Namespace Naming Guidelines
I got it as an answer from Konamiman to my question which is related to yours.