Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# WinForm
Hi all,
Our application consists of several solutions. It uses MEF to plugin functional parts, that is all fine.
 
I now try to find a way to share resources across all of those projects.
Currently I create a dll containing a public resource file hosting images I need in all of my other projects.
I reference the dll containing the resource file and I can access all of the images... from code.
 
Is there a way to have the designer support such a referenced rersource dll?
I'd like to select the images in the designer and not manipulate the Form.Designer.cs or initialize them myself from code.
 
I also tried to inherit from the Resource.Designer.cs, but that also didn't work out. I can access the images, but again only from code (beside the fact that it is regenerated every time I add/remove elements from the inheriting resource file - which won't be a big problem because logically it should not be changed)
 
Any help is kindly appreciated,
cheers
Andy
Posted 26-Jan-12 5:39am
Edited 26-Jan-12 5:56am
v4
Comments
Marcus Kramer at 26-Jan-12 11:17am
   
A very interesting question. +5 for that. I have no idea how to approach this one, but I'm curious to see what some of the others come up with.
hoernchenmeister at 26-Jan-12 11:20am
   
So am I ;)
SAKryukov at 26-Jan-12 13:50pm
   
Well, I agree, also voted 5.
You can get an idea how to approach this if you read my answer -- hope you will find it interesting, too.
--SA
BillWoodruff at 26-Jan-12 12:43pm
   
+5 for, as Marcus commented, a very interesting question !
SAKryukov at 26-Jan-12 13:51pm
   
I agree, also voted 5.
 
I you find this question interesting, you might find my answer interesting, too, please see.
--SA

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Resources are designed to be internal to the assembly. However, the problem is solvable. You need to put all resources in one or more special resource-only assemblies and provide a special facade class (or classes) used exclusively to expose the resource to the assemblies referencing your resource assemblies. A typical form of exposure should be a public static property of a static class.
 
(See http://en.wikipedia.org/wiki/Facade_pattern[^].)
 
For one thing, this will present a certain maintenance hassle: as soon as you change or add a new resource, you will need to change the facade class: add a property or modify the implementation of existing property, usually just a name if internal property. Also, it looks like a functional redundancy. (But do you have a choice without redundancy?)
 
From the other hand, the facade class is trivial, maintenance is not tricky, and it can give you a layer for additional flexibility, so the interface can be done in a more semantic style from the perspective of the referencing assembly (user assembly). I can explain.
 
For example, you need to add N images. The best way of doing it through the designer is this: you add the *.res resources using the Designer as separate image files using "Add existing file". The designer will copy the file in the project directory structure (make sure it would not produce double copies, you only need to keep the target copy in the project), add the reference file to the project file with appropriate attributes (instructing the MSBuild: embedded resource, don't copy to the output directory), it will also add the reference to the file to the resource file and — important — will auto-generate the source file. Look at this source file: you will find some static class and some static property with the name close to the name of the image file. The best thing is: if the file type is JPEG or PNG, the type of the static property is Image. Same thing with many other resource types. You don't have to use resource stream, read or convert anything; you already have a fully-initialize static Image. Or string in the case of the text file, or something else.
 
So far so good, but the only problem is when you use many image files, the writer of the code using the resources should use the semantic (hopefully) variable names (very good that not strings as the compiler would not able to check it they are correctly spelled), but what if there are too many? The access to the many resources is not structured.
 
As you have a facade class(es) in my approach, you can use the extra flexibility to restructure the access. For example, you can group those image variables into some structures by semantic criteria or even present them as a collection indexed by an enumeration type and/or enumerate in a cycle by a enumeration-type index.
 
(By the way, you can learn how to enumerate by a enumeration type index from my article: Enumeration Types do not Enumerate! Working around .NET and Language Limitations[^].)
 
—SA
  Permalink  
v4
Comments
Marcus Kramer at 26-Jan-12 16:21pm
   
Of course. I totally didn't think of using the facade in this case, but should have. Well explained. +5.
SAKryukov at 26-Jan-12 16:28pm
   
Thank you, Marcus.
The "facade" in not much more then just a term and the idea. The essence is in how resources work and how assemblies can use each other.
--SA
hoernchenmeister at 27-Jan-12 4:11am
   
Thanks a lot SA for your explanantion.
Unfortunately I have a hard time to follow...
I got that part with the facade class though, but I somehow struggle with the rest. Would you mind helping me understanding this in its depths (no code, I really want to get the idea).
 
If I got it right I need a resource assembly first. So I went ahead and created a class library containing a resource file that hosts some images. I added a class too, to be able to load that assembly with a ResourceManager in case this will become useful somehow. I compiled and now I have a dll.
 
Then I created a WinForm project for testing purposes.
You wrote: "For example, you need to add N images. The best way of doing it through the designer is this: you add the *.res resources using the Designer as separate image files using "Add existing file""
Hopefully you don't think I am stupid, but I just don't get it ;)
I can translate it into my mother language, but I am not really sure what you mean here.
Do you mean add the *.resx file from the resource assemblies project as existing file to the test-project?
 

Regarding the facade, besides my tries above I created another class library project containing a resx file with some images. There I added a static class that exposes the images from the resx via an enumerator (exmpl. enum GlobalImages{Delete, Edit, New}). I am now able to get the images in other applications from code.
Just to make sure I explained my question correctly. My colleague now can use the dll and get images in a controlled way, which is really good. But for example, if he has a form with a button on it he want's to set the image for the button using the property window of the designer. Which is not possible because he can only select from .resx in the project.
Will your approach make this possible?
 
Thanks a lot for your efforts SA,
it is always a pleasure (even if it sometimes hard for me to follow in the first place) reading your explanations, answers and articles. I already learned a lot in the past, and will of course continue to do so in the future :)
 
cheers
Andy
SAKryukov at 23-Feb-12 13:27pm
   
Hi Andy,
 
I'll try to answer.
 
First, how to create resources. My "...you add the *.res resources using the Designer..." was perhaps just too short, just because I assume you will know what to do; my text was not to show the steps but to remind you about something which you could already see in the IDE. Now, to show the steps, I'll need to open the IDE...
 
Let's say you have just created an item in your project: [some directory node in the Solution Explorer] -- [context meny] -- Add... -- New Item... -- ["Add New Item" window"] -- [...list] -- Resource File -- selected a name "Images.res".
 
If will create just two files: "Images.res", and "Images.Designer.cs"; and two nodes in the Solution Explorer tree, one a child of another. When you double click (or "Open") "Images.res", you will get to the Designer window in the source code area, in a separate tab (usually); it has a smaller menu on the top: "Strings", "Add resource", etc.
 
You want to use "Add Resource" -- "Add Existing File". Suppose you have some image file "firstImage.png". Add it in this way. The file 1) will be copied into your project (so make sure you does not appear twice; it it was inside your project's sub-directory, you don't need it's first copy, you only need the one created by the designer), 2) it's name added to the project file (you will see it in the Solution Explorer's project tree as a node), 3) in a project, is will get the properties like a resource and "don't copy" (to the output; because it will be embedded instead), 4) it's name will be referenced in "images.res".
 
Now, all changes will be use in auto-generated code "Images.Designer.cs". You are not supposed to modify this code, ever, but just look into it. You will find some static variable named based on "firstImage". The type of this property is already Image. You can use it immediately through its name. You don't have to read it from resource or anything. It's already done.
 
Now, you create a facade class and expose some properties of the static class generated in "Images.Designer.cs" using "public".
 
The question is how to use them in Designer. Now, it's my turn to wonder: what, are you programming through Designer?! Well, don't do it! Designer is designed to help to do the fist demo very quickly but slow down the reuse and maintenance, to make it barely supportable and not reusable. You really need to use the Designer just to put all the panels and some (not all) of other controls to design a general layout of the form. You can modify just the names of the members (but refactorization menu is much better then the designer), and adjust such properties as Dock and Padding, to be able to see the result immediately. But even this is dangerous for support. Imagine you need padding of 5. It means that you will create a lot of different padding object with 5 and 0 (to avoid 5+5). What happens when you need to change 5 to 6 consistently? Designer sucks. Every time you do any repeated work in programming, you do something wrong. Designer is manual work, writing code is not, in contrast to common wrong believe. Setting images from resource in Designer is bad and not portable. This is good that the Designer does not support changing images taken from external resource assembly -- it helps you to avoid yet another mistake. Designer eliminates code reuse, but your question was about reuse.
 
More than that, using code is perfectly save. In this approach, you do not hard-code anything. Your static member in the auto-generated resource file (this is where the resource Designer is good to use) has the name which is checked up with a compiler. Should you change is, it won't compile.
 
--SA
hoernchenmeister at 13-Mar-12 4:40am
   
Hi SA,
I now understand what you explained. It's sometimes hard for me to get the "message", even if I my english is quite good (in my opinion at least).
I do know how to deal with resources, I just couldn't put it all together.
I really appreciate all the efforts you made to help me out and to explain it as nicely as you have done it.
I have finally chosen the facade approach and stopped trying to use the designer. That's also the reason for the long period of time that passed by until I finally started to write down these lines.
 
You made a big impact on my way of thinking regarding the use of the designer. I use the designer primarily to set up my forms and to interact with third party tools (Infragistics) that provide helper windows to adjust complex components quite fast. Additionally I use Resharper for the refractoring purposes, but I never looked at the designer itself the way you described it.
It took me some thinking and I needed to drop some opinions I gained over the years, but you are pretty much right with what you've said.
Especially the "reusability part", because I strive to create reusable things if applicable (I remeber heated discussions with my superior trying to convince him that we need libraries so that we can reuse things that have already been done before - when I started here they were pretty much on VB6 only without anything beeing reusable and on forms only).
 
So finally I want to thank you for your input on this topic and for the way you try to help me with my problem.
I appreciate that you tried to make me look at that problem in a different way. Isn't that the way to become better?
Moving your head into a different direction to gain knowledge instead of sticking to old habits due to comfort purposes?
I think it is.
 
I really got much more out of this post than I have thought in the first place.
 
thanks again SA and have a great day,
best regards
Andy
SAKryukov at 14-Mar-12 3:27am
   
Hi Andy,
 
Thank you very much for this message and all your good words.
 
I am very happy to meet such a well-understanding person. This is pretty rare, because people are driven by their own way of thinking too much to pay enough attention to arguments of other people. This is called "imprinting" and dominates absolute majority of people (quite frankly, including myself; I'm trying to fight it, but this is of course needs a lot of effort).
 
However, there is a difficult trade-off between established way of one's own thinking and being easily diverted by arguments and "advertizement" of other people. The second problem could be even more difficult (well, it depends on relative levels of the given person versus the level of others, but who can evaluate it?). Sometimes it's much better to keep skepticism and keep your own views. The visible phenomena is the easy falling of many people into "cool" and "trendy", which is more usually just the dirty foam on the water, a garbage on the surface of technology (arts, even science or whatever else).
 
(Just one interesting real-life example: I worked several months for the company where they fired a team or about 30 people working at robotic system, left one and hired myself and two more, I lead this small team; people said that the previous team spent months to create a 3D animated model of moving robotics parts before they managed to physically move one single servo motor; and the legacy code I found was working but full of deadlocks and race conditions. Well, who would argue? We are too lazy to happily go where we can move the motors... :-)
 
Going out of comfort zone is one of the components of any progress. But doing so by just reading may be blessing but may be a problem as well. First, it is not possible to read and properly understand everything. Also, this is very individual. For me, I found it much more useful to avoid reading on new problem at first, but try to solve the whole problem by myself from scratch. Waste of time to reinvent the wheel? Not exactly. First, you can really invent something which other people did not manage to find. A remote one, but still a chance. Second, you may not understand the matter well enough before you break your own teeth trying to attack it. Does it sound like making some sense to you?
 
Well, thank you again. If interested, you can also contact me directly via my Web site which you can find by my CodeProject profile, it has a "Contact me" form. By the way, you English sounds very nice to me.
 
Cheers,
--SA
hoernchenmeister at 14-Mar-12 5:51am
   
Hi SA,
that indeed makes sense to me. I believe that the "Comfort Zone" is one of the biggest enemy of personal and professional evolution.
On the one hand I can understand that people use existing solutions to fix their problem fast without using the opportunity to learn something new if they have tight deadlines. That also happens to me from time to time, but it always leaves a bad taste... a wasted chance to improve oneself still is what it is... a wasted chance.
On the other hand I believe that the job we are doing requires an open mind that needs to be let loose from time to time to gain new impressions, new ideas or just needs to be fed with some articles that would never appear on my schedule when sticking to the projects I deal with only. This is what fascinates me so much, the sheer endless options to evolve if you just keep on being curious. Programming something offers the possibility to be one of the most creative professions I ever came along if you want it to be that way. A little bit like painting or making music. And its one of the rare professions where the borders of how far you can go are drawn by yourself only.
 
In the modern, fast paced world where profit justifies a lot, curiousness is a habit that is sometimes hard to cultivate.
Luckily I had the opportunity of having a great mentor when I started learning to program. He taught me a lot of the soft skills and alwas tried to let us find the solution ourselves by just putting our heads into the right direction from time to time. Just as I mentioned above he always told us to take a chance to learn something new whenever possible. Even if it sometimes look off-topic, you never know what you can make out of it someday.
You remind me of him though, he had an equal style of explaining things and understood that helping someone to find the solution on their own is much more valuable than just providing the solution itself.
So please keep it up ;)
 
Thanks again Sergey, take care and best regards
Andy
SAKryukov at 14-Mar-12 12:33pm
   
I think I understand you perfectly.
 
By the way, I feel really uncomfortable when I see typo and other mistakes and cannot fix them (by some reason I saw a good number of them in your last post, could not stand fixing them).
Because --
http://www.youtube.com/watch?v=u9_kahA_wQo&feature=fvsr
(please see)
 
Thank you, best wishes,
--SA
hoernchenmeister at 15-Mar-12 8:10am
   
That's fine Sergey, and it helps not making me look stupid ;)
Normally I run my messages through a spellchecker, but it seems I missed that somehow.
Luckily I will not be a target to the Grammar Police anymore ;)
 
cheers and have a great day
Andy
SAKryukov at 15-Mar-12 21:30pm
   
Hope you liked the show. I wish someone fixed my own mistakes. I highly prefer to be understood correctly, and looking not stupid would probably be a super-goal. :-)
This concern is the reason why I always use Mozilla SeaMonkey: edit fields are spell-checked as you type -- highly recommend.
--SA
SAKryukov at 23-Feb-12 13:26pm
   
[misplaced...]

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 555
1 Kornfeld Eliyahu Peter 409
2 Maciej Los 369
3 DamithSL 196
4 OriginalGriff 188
0 OriginalGriff 6,353
1 DamithSL 4,854
2 Maciej Los 4,466
3 Kornfeld Eliyahu Peter 4,058
4 Sergey Alexandrovich Kryukov 3,897


Advertise | Privacy | Mobile
Web01 | 2.8.141220.1 | Last Updated 26 Jan 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100