We build a lot of components, WinForms, Workflow activities etc, and something that we use a lot is the 'Designer' attribute.
The general practice during initial development is, the Designer attribute is used with the [Designer(typeof(DesignerType))] style to get things working - then later, this is converted to [Designer("AssemblyQualifiedTypeName")], which allows the designer DLL to be removed from the component's reference list - this removes the need for the component consumer to have to deploy the designer DLL with their product.
This practice of splitting the design-time, and run-time code into two seperate DLLs is common practice, and one that I am a proponent of.
A negative side effect, is the 'assembly qualified type name' will include the assembly version of the designer dll, so when the version is incremented, one must perform a 'search and replace' across the product to ensure they have updated all the 'loose references' to this designer.
Finally, my question:
Can anyone reccomend a best practice that doesnt rely on 'search and replace', which can manage all these references, to ensure they are always up to date?
We often get a lazy developer forgetting to update the reference string, resulting in a new version of the component linking to the previous version of the designer DLL - which of course doesnt get deployed, so design-time support is lost.
Perhaps some form of pragmas, macros, build script, magic attributes, I dont know, but there must be a better way of doing this.
Anyone? (thanks)
Why not create a single designer that uses something like the Managed Addin Framework or Activator.CreateInstance internally to pick and show a designer? With this technique, the Designer attribute would never have to change...
Do it like Microsoft does. Take a look at AssemblyRef class (System.Windows.Forms.dll) in Reflector.
Related
I have a project where I want only one class to have access to a dll. I would be content with hiding the dll from intellisense, but still having access to it if that is an option. Either way, I want only one class to use the dll and for it not to be seen and/or accessible otherwise.
I'm using C# in visual studios.
Simply said: You can't do that (but keep reading).
Basically, a DLL (From the .NET perspective) is a bunch of code and config files. No more than that. So, given that you'll need to make public those classes in order to be used from another ones outside that assembly then you can not.
What you can do (I ended up doing this a few years ago) is to use some kind of reflection to determine which class (and namespace) is trying to access your assembly and only permit the proper one.
Other way is to implement a key negotiation between your DLL and the permitted assembly. You'll need to implement those manually, as far as I know.
Anyway, keep in mind there's always a way to bypass this kind of protection by disassembling and modifying your code. So, at least, don't forget to obfuscate the file. Anyway, this will just make it a little more painful, but still possible.
An alternate approach, if you goal is to stop people using the functionality of the dll by accident is to push your wrapper class into an intermediary assembly. Your project then references that intermediary project, rather than the underlying dll which effectively hides it. So your project structure would change to something like this:
Main Project -> references API Wrapper Project -> references API DLL
For this to work, your wrapper project needs to make sure that it doesn't accidentally expose any of the API DLL classes through its public interface.
Obviously this doesn't stop your developers from going in and adding a reference to the API DLL so that they can use the library directly, but if the goal is to stop accidental access to the API DLL classes because intellisense has helped the developer out a bit too much then it might be a viable option.
I am developing a winforms application, and I want to place the designers into a separate project, because it requires the reference to .Net full framework (System.Design), while the application itself requires .Net framework client version only.
I have 3 projects:
TestControls with TestUserControl
TestControls.Designers with PanelHodelerDesigner
TestApp to test the TestUserControl
TestControls and TestControlsDesigners are signed and registered in GAC.
When I define Designer for the user control as follows, VS cannot locate the designer
[Designer("TestControls.Designers.PanelHolderDesigner, TestControls.Designers")]
public partial class TestUserControl : UserControl, IPanelHolder
{
...
}
When I change it to fully qualified name including version, culture and publicKeyToken like follows, VS loads the designer correctly.
[Designer("TestControls.Designers.PanelHolderDesigner, TestControls.Designers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=520302431ebc763b")]
public partial class TestUserControl : UserControl, IPanelHolder
{
...
}
All samples in the web that I found teach that I should use shorten version. Why it does not work for me? What else should I do to use the short version of designer attribute?
Feature, not a bug. The GAC was designed to be able to store multiple versions of an assembly side-by-side. If you don't specify the [AsssemblyVersion] then the CLR doesn't stand a chance to guess at the correct one. So it doesn't try, it only looks in the probing path of the running app for the display name. These "samples" you found probably all assume that you don't use the GAC.
It is probably going to be difficult to talk you out of this, but separating the designer from the control isn't a great idea. Microsoft does this, but they are extraordinarily reluctant to ever change the [AssemblyVersion] of a .NET Framework assembly. And expend massive resources to ensure they never have to. That's is very hard to duplicate, versioning assemblies is rather important to mere mortals like us, we don't spend three or more years on designing and testing assemblies to ensure that the hundreds of thousands of programmers that use them don't run into trouble.
Short from having trouble on your own machine, getting this to still work correctly on another programmer's machine is hard enough in itself. I never hesitate to use typeof() in the [Designer] attribute and include the designer with the control. Never a surprise that way. That's a spit of IL that never gets loaded at runtime, taking advantage of the you-don't-pay-for-what-you-don't-use CLR behavior is hard to pass up when it solves icky problems like this.
I need to declare an attribute for coverage exclusion in my code, the issue is that i have a project group and i wish to create it somewhere where i can access it from all projects when i need it, right now i have it outside of the namespaces so it would be easier to use, and its declared in each project like:
public class CoverageExcludeAttribute : Attribute
{
}
is there any better way to achieve this goal in a way it could be access anywhere in my project group and declared only once, without having to add its namespace (e.g by using the global namespace) to each file i use the attribute in?
Thank you
While I actually agree with P.Brian.Mackey, I think the only way to do it is exactly as DjKraze said:
Create a new micro-project of type ClassLibrary, add a single .cs file with your Coverage(..) class and ensure that class is inside no namespaces block. Then build it and for each one of the other projects do a Add-Reference to that micro-project you just created.. That way it will surely work, and you will have a handy place to put any further 'common code' to be available everywhere.
However, each project will have to be updated with the reference. This is the minimum requirement - all in all, if you want to use anything instead of copying, it must be referred..
Sorry, almost no other options for such thing!
The other way is to .. ugh, copy. You can easily set up a simple pre-build script that will copy given .cs file to each one of your projects, but "adding" the file to the .csproj's build list is a bit harder, still possible with use of some Ruby or Python or friends...
Hm.. saying that, It may be possible to write a pre-build script to inject a reference to the micro-project automatically.. But I wont know if this is worth doing. Do you have more than 50-100 projects? Else, probably it's not worth..
This only applies to VS2010 and above
If you want some source code defined in each of your projects, but without a project reference, take a look at some of the functionality provided by NuGet, especially Source Code Transformations. These allow the addition of some source code to the project when you add the NuGet package to the project.
You can use Dependency Injection
http://en.wikipedia.org/wiki/Dependency_injection
The most popular are: Microsoft Unity, Ninject, NHibernate, StructureMap, Autofac.
Good luck!
Ive been looking everywhere for a possible solution to this but can't seem to find an answer. My issue is that I have a few classes that need to completely hidden from Assembly.getTypes, as I'm writing a plugin for an application, and it's picking up types that I need to remain hidden (this happens even if they are declared as private or internal classes).
anyone know how to either alter what assembly.GetTyes returns, or an ,aficionado attribute that will keep those types from being listed?
This is quite a hack and is very fragile, but could work.
Create 2 assemblies -- one for the plug-in and the second for the other types. The second would be placed in another known directory and loaded dynamically into the first when needed. (For example, via Assembly.LoadFrom.)
The first assembly would then be placed in the plug-in directory and only ever publish its types. This very fragile because you would likely have to hard-code a path to the second assembly and you run the risk of the file getting deleted or moved.
EDIT
#SLaks' comment takes away the fragility of this solution. If you embed the second assembly as a resource and load it at run-time, the app calling Assembly.GetTypes won't see the types you want hidden.
This is not possible.
Sorry.
Code that calls Assembly.GetTypes() should typically filter for only public types.
Welcome to managed code. Complete type information is necessary to .NET's type verifier. Only native code can be hidden from .NET metadata, and then you give up the portability and permissions supported by pure MSIL.
Question in the title.
I'd like to avoid recompiling since the source code I'm modifying is third party and I'd like to use the original binaries where possible, and replace only the assembly which contains the class I modified. But I'm not sure if this is a safe thing to do. In C++ for example this is definitely a bad idea.
No.
The assemblies that reference your library refer to methods and types using (some form of) name, so as long as you don't change the names of public types and methods (used by other assemblies), you don't need to recompile any of the assemblies - they will work with the updated version of the library.
In most cases Tomas answer is correct, but there are some cases where it is not true:
When using strong naming (signing) change of a single character leads to a new signature, thous leading to a new strong name.
Setting in your project references for your assembly the property Specific Version to true and changing the version number manually or automatically in AssemblyInfo.cs
No. All other assemblies will automatically work with the newly updated library.