Automagically convert properties to auto getter/setter - c#

I've generated a code base for service communication from a WSDL file which resulted in around 100 classes containing the following:
public class SomeClass {
private string _someVar;
public string SomeVar {
get { return _someVar; }
set { _someVar = value; }
}
}
Is it possible to automagically turn everyone of them into auto properties? Maybe using ReSharper or some regex magic?

If you just need to do this once, you can let R# do it for you with a Code Cleanup action.
Right-click on the project (or solution, or single source file), select "Cleanup code..." and then use profile which includes "Use auto-property, if possible." (If you don't have such a profile already, you can edit your profiles from that dialog.)
However, I would strongly advise you to separate generated code from hand-written code. Make all your generated code use partial types (and potentially partial methods) - that way you can create a hand-written partial type which merges with the auto-generated code, without being in the same file. You don't need to look at the generated code, and you can replace it with another version later without worrying about any custom changes.

The following Visual Studio regex will find the pattern you have above when plugged into the "Find & Replace" tool.
private:Wh*:i:Wh*:i;:Wh*public:Wh*(:i):Wh*(:i):Wh*\{:Wh*get:Wh*\{[^\}]*\}:Wh*set:Wh*\{[^\}]*\}:Wh*\}
And this pattern will do the replace.
public \1 \2 { get; set; }

Related

"Type is not defined" when I want to add my custom class as settings type

I want to add this class as setting's type:
using System.Collections.Generic;
using System.Configuration;
namespace MY_PROJECT.SUB_PROJECT
{
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public class Configs: List<ConfigData>
{
Configs(int capacity): base(capacity) { }
public string GroupName { get; set; }
}
}
So what I did:
Select Browse... in the type dropbox:
I cannot see the MY_PROJECT namespace anywhere:
So I typed the full type manually:
The result is an error:
Type 'MY_PROJECT.SUB_PROJECT.Configs' is not defined.
I also tried SUB_PROJECT.Configs and Configs alone. Nothing helped. Why does my class not show in the browser?
In order to pull something in as a reference you need to have it compiled as a dll file. In Visual Studio they refer to this as a "Library" which is really just a class without a main function. Other option is to just leave it in the same namespace and pull the class into whatever else your working on.
I just had this issue and it was due to an Inconsistent accessibility error. Make sure that any 'required' type/field is globally accessible (public?). For the OP's case, making the constructor public solves the issue:
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public class Configs: List<ConfigData>
{
public Configs(int capacity): base(capacity) { }
// ^^
public string GroupName { get; set; }
}
In my case this was the problem:
internal struct NativeType
{
//...
}
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public class NativeTypeWrapper
{
public NativeType type; // This will not work because NativeType
// is less accessible than NativeTypeWrapper...
}
I had this problem as well. I was doing exactly the same: creating a custom class to use in Application Settings. In my case, I followed the steps outlined in this very informative article:
http://www.blackwasp.co.uk/CustomAppSettings.aspx
I should note the article is written for C#, and I painstakingly converted it to VB until it worked. I had to solve the Type...is not defined error the hard way: relentlessly experimenting until I got it to work.
I will describe my first solution, one which was not mentioned in the article, probably because it's for C# instead of VB, and that is: put the custom class or classes each in their own .vb files. For instance: Employee.vb and Room.vb. This is the only way I could make it work perfectly with no errors. After doing this and rebuilding the solution, I was then able to add my custom class as an Application Setting, but of course only by manually typing the full name TestProject.Employee in the Select a Type dialog.
However, following the article I linked above, if I put all the class definitions in the Module1.vb file with Sub Main(), the Select a Type dialog cannot find them, and I receive the Type...is not defined error.
And the cause of this error seems to be shortcomings in the code & design of the Applications Settings system and Settings page of the Project Properties dialog. I say this because of the solution I found: I hacked my classes into the settings the hard way.
What I mean by that is I initially created the setting with the name DefaultEmployee and type of String. Then I used the Find In Files dialog to find all instances of DefaultEmployee and replaced the appropriate instances of String with TestProject.Employee.
The files I made replacements in are: App.config, Settings.Designer.vb, and Settings.settings.
And it worked..! Sort of. I should say the code ran fine and it did what was expected. But...the Application Settings dialog didn't like it. After I made the changes, there are various errors from the Project Properties/Settings system every time I opened it. But as I said, it still works.
Thus...my only conclusion is the coding of the Settings system is not designed to handle this situation, and if you wish to have the most reliable & error-free experience, it's best to put each of the custom classes in their own .vb class file.
On the other hand, if you wish to become very adventurous, you could create your own Applications Settings system, as the author of this article did. I have not read all of this yet, but scanning through it seems very interesting:
https://weblog.west-wind.com/posts/2012/dec/28/building-a-better-net-application-configuration-class-revisited

Generate .net dll wrapper around existing .net library

I have a dll named ExpensiveAndLargeObfuscatedFoo.dll.
Lets says it defines a type named ExpensiveAndLargeObfuscatedFooSubClass.
It's been compiled for .NET.
Are there any tools (free, paid, whatever) that will generate c# or vb class files that will do nothing but wrap around everything defined in this expensive dll? That way I can add functionality, fix bugs (that CorpFUBAR won't fix), add logging, etc?
Literally, I want output that looks like this
namespace easytoread {
public class SubClass {
private ExpensiveAndLargeObfuscatedFoo.SubClass _originalSubClass;
public SubClass() {
this._originalSubClass = new ExpensiveAndLargeObfuscatedFoo.SubClass ();
}
public string StupidBuggyMethod(string param1,int param2) {
return _originalSubClass.StupidBuggyMethod(param1, param2);
}
}
}
It would have to handle custom return types as well as primitives
namespace easytoread {
public class SubFooClass {
private ExpensiveAndLargeObfuscatedFoo.SubFooClass _originalSubFooClass;
public SubFooClass() {
this._originalSubFooClass= new ExpensiveAndLargeObfuscatedFoo.SubFooClass ();
}
private SubFooClass(ExpensiveAndLargeObfuscatedFoo.SubFooClass orig) {
this._originalSubFooClass = orig;
}
public SubFooClass StupidBuggyMethod(string param1,int param2) {
return new SubFooClass(_originalSubFooClass.StupidBuggyMethod(param1, param2));
}
}
}
And so on and so forth for every single defined class.
Basically, poor mans dynamic proxy? (yay, Castle Project is awesome!)
We'd also like to rename some of our wrapper classes, but the tool doesn't need to do that.
Without renaming, we'd be able to replace the old assembly with our new generated one, change using statements and continue on like nothing happened (except the bugs were fixed!)
It just needs to examine the dll and do code generation. the generated code can even be VB.NET, or ironpython, or anything CLR.
This is a slippery slope and I'm not happy that I ended up here, but this seems to be the way to go. I looked at the Castle Project, but unless I'm mistaken that won't work for two reasons: 1) I can't rename anything (don't ask), 2) none of the assemblies methods are declared virtual or even overridable. Even if they were, there's hundreds of types I'd have to override manually, which doesn't sound fun.
ReSharper can do much of the work for you.
You will need to declare a basic class:
namespace easytoread {
public class SubClass {
private ExpensiveAndLargeObfuscatedFoo.SubClass _originalSubClass;
}
}
Then, choose ReSharper > Edit > Generate Code (Alt+Ins), select "Delegating Members", select all, and let it generate the code.
It won't wrap return values with custom classes (it will return the original type), so that would still have to be added manually.
It seems the best answer is "There is no such tool". So, I'll be taking a stab at writing my own later as an off-hours project. If I ever get something useful working I'll github it and update here.
UPDATE
Visual Studio 2012 Fakes seem to be promising. http://msdn.microsoft.com/en-us/library/tfs/hh549175(v=vs.110).aspx - we've moved on but I might try creating a fake and then dropping it in as a replacement dll sometime in the future
If you have access to the source code, rename and fix in the source
code.
If you don't have access (and you can do it legally) use some
tool like Reflector or dotPeek to get the source code and then,
goto to the first point.

Refactoring duplicate code when the only difference is the type of one variable?

I have to be able to connect to two different versions of the an API (1.4 and 1.5), lets call it the Foo API. And my code that connects to the API and processes the results is substantially duplicated - the only difference is the data types returned from the two APIs. How can I refactor this to remove duplication?
In Foo14Connector.cs (my own class that calls the 1.4 API)
public class Foo14Connector
{
public void GetAllCustomers()
{
var _foo = new Foo14WebReference.FooService();
Foo14WebReference.customerEntity[] customers = _foo.getCustomerList;
foreach (Foo14WebReference.customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(Foo14WebReference.customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
And in the almost exact duplicate class Foo15Connector.cs (my own class that calls the 1.5 API)
public class Foo15Connector
{
public void GetAllCustomers()
{
var _foo = new Foo15WebReference.FooService();
Foo15WebReference.customerEntity[] customers = _foo.getCustomerList;
foreach (Foo15WebReference.customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(Foo15WebReference.customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
Note that I have to have two different connectors because one single method call (out of hundreds) on the API has a new parameter in 1.5.
Both classes Foo14WebReference.customerEntity and Foo15WebReference.customerEntity have identical properties.
If the connectors are in different projects, this is an easy situation to solve:
Add a new class file, call it ConnectorCommon and copy all of the common code, but with the namespaces removed. Make this class a partial class and rename the class (not the file) to something like Connector.
You will need to add a link to this to each project.
Next, remove all of the code from your current connector classes, rename the class (not necessarily the file) to the same as the partial class, and add a using statement that references the namespace.
This should get what you are looking for.
So, when you are done you will have:
File ConnectorCommon:
public partial class Connector
{
public void GetAllCustomers()
{
var _foo = new FooService();
customerEntity[] customers = _foo.getCustomerList;
foreach (customerEntity customer in customers)
{
GetSingleCustomer(customer);
}
}
public void GetSingleCustomer(customerEntity customer)
{
var id = customer.foo_id;
// etc
}
}
File Magento15Connector
using Foo15WebReference;
partial class Connector
{
}
File Magento14Connector
using Foo14WebReference;
partial class Connector
{
}
Update
This process can be a little confusing at first.
To clarify, you are sharing source code in a common file between two projects.
The actual classes are the specific classes with the namespaces in each project. You use the partial keyword to cause the common file to be combined with the actual project file (i.e. Magneto14) in each project to create the full class within that project at compile time.
The trickiest part is adding the common file to both projects.
To do this, select the Add Existing Item... menu in the second project, navigate to the common file and click the right-arrow next to the Add button.
From the dropdown menu, select Add as link. This will add a reference to the file to the second project. The source code will be included in both projects and any changes to the common file will be automatically available in both projects.
Update 2
I sometimes forget how easy VB makes tasks like this, since that is my ordinary programming environment.
In order to make this work in C#, there is one more trick that has to be employed: Conditional compilation symbols. It makes the start of the common code a little more verbose than I would like, but it still ensures that you can work with a single set of common code.
To employ this trick, add a conditional compilation symbol to each project (ensure that it is set for All Configurations). For example, in the Magento14 project, add Ver14 and in the Magento15 project add Ver15.
Then in the common file, replace the namespace with a structure similar to the following:
#if Ver14
using Magneto14;
namespace Magento14Project
#elif Ver15
using Magneto15;
namespace Magento15Project
#endif
This will ensure that the proper namespace and usings are included based on the project the common code is being compiled into.
Note that all common using statements should be retained in the common file (i.e., enough to get it to compile).
If the FooConnectors are not sealed and you are in control to create new instances, then you can derive your own connectors and implement interfaces at the same time. In c# you can implement members by simply inheriting them from a base class!
public IFooConnector {
void GetAllCustomers();
}
public MyFoo14Connector : Foo14Connector, IFooConnector
{
// No need to put any code in here!
}
and then
IFooConnector connector = new MyFoo14Connector();
connector.GetAllCustomers();
You should introduce an interface that is common to both of the implementations. If the projects are written in the same language and are in different projects, you can introduce a common project that both projects reference. You are then making a move towards having dependencies only on your interface which should allow you to swap in different implementations behind the scenes somewhere using inversion of control (google, dependency injection or service locator or factory pattern).
Difficulties for you could be:
1) Public static methods in the implementations are not able to be exposed staticly via an interface
2) Potentially have code in one implementation class ie Foo14Connector or Foo15Connector that doesnt make sense to put into a generic interface

How do I get the application's directory from my WPF application, at design time?

How do I get the application's directory from my WPF application, at design time? I need to access a resource in my application's current directory at design time, while my XAML is being displayed in the designer. I'm not able to use the solution specified in this question as at design time both System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) and System.Reflection.Assembly.GetExecutingAssembly().Location point to the IDE's location (Visual Studio... Common7 or something).
Upon request to further clarify my goals: I want to access a database table at design time and display a graphic of that data. The design is done in Visual Studio 2008, so what I need is a very specific solution to a very specific problem, and that is getting the assembly directory for my app.
From your description it sounds like your code is actually running inside the WPF Designer within Visual Studio, for example it is part of a custom control library that is being used for design.
In this case, Assembly.GetEntryAssembly() returns null, but the following code gets the path to the application directory:
string applicationDirectory = (
from assembly in AppDomain.CurrentDomain.GetAssemblies()
where assembly.CodeBase.EndsWith(".exe")
select System.IO.Path.GetDirectoryName(assembly.CodeBase.Replace("file:///", ""))
).FirstOrDefault();
The following steps can be used to demonstrate this works inside VS.NET 2008's WPF Designer tool:
Place this code inside a "WPF Custom Control Library" or "Class Library" project
Add whatever code is necessary to read the database and return the data for display (in my case I just returned the application directory itself as a string)
Reference the library project from the project you are designing
Use the custom controls or classes from a XAML file to populate your DataContext or otherwise supply data to your UI (in my case I bound DataContext using x:Static)
Edit that XAML file with the "Windows Presentation Foundation Designer", which can be done by just double-clicking unless you have changed your default editor, in which case use "Open With..."
When you follow these steps, the object you are looking at will be populated with data from your database the same way both at run time and design time.
There are other scenarios in which this same technique works just as well, and there are other solutions available depending on your needs. Please let us know if your needs are different those I assumed above. For example, if you are writing a VS.NET add-in, you are in a completely different ball game.
Are you trying to support a designer (such as the visual studio designer or Blend)?
If so then there are various different ways to approach this problem. You typically don't want to rely a relative path from executable because it can be hosted in various different design tools (VS, Expression Blend etc..)
Maybe you can more fully explain the problem you are trying to solve so we can provide a better answer?
I don't think this is possible - you're asking for the location of an assembly that potentially hasn't even been built yet. Your design-time code does not run inside your application and would have to make some assumptions about the IDE. This feels wrong and brittle to me - consider these questions:
Has the project been built yet?
If not, there is no executable to get the path of, so what then?
Would the other files be present if it hasn't been built, or are they build artefacts?
If it has been built, where was it built to?
Do you need to consider other IDEs?
In this situation you should probably ask the user, at design time, to provide or browse for a path by adding a property on your object for them to edit. Your design time code can then use the value of the property to find what it needs.
If you are extensively working on WPF designers using adorner etc, please use "Context" property/type
Details:-
In Design time you have instance of modelItem (I assume it, you know it) if not then you can instantiate it in Override implementation of Activate method
// in DesignAdorner class
public class DesignAdorner : PrimarySelectionAdornerProvider
{
protected override void Activate(ModelItem item)
{
modelItem = item;
}
}
Now you can access the current application path using following single line code
string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName;
Let me know, if it does not help you.
Ok given the further clarification here is what I would do.
staying in line with the concern raised by GraemeF, doing what you want is brittle and prone to breaking at best.
Because of this the general practice is to treat design time data support as a wholly different approach then runtime data support. Very simply, the coupling you are creating between your design time environment and this DB is a bad idea.
To simply provide design time data for visualization I prefer to use a mock class that adheres to a common Interface as the runtime class. This gives me a way to show data that I can ensure is of the right type and conforms to the same contract as my runtime object. Yet, this is a wholly different class that is used for design time support (and often used for Unit Testing).
So for example. If I had a run time class that needs to show person details such as first name, last name and Email:
public class Person()
{
public String FirstName { get; set;}
public String LastName {get; set;}
public Email EmailAddress {get; set;}
}
and I was populating this object from a DB at runtime but also need to provide a design time visualization I would introduce an IPerson interface that defines the contract to adhere to, namely enforces that the property getters exist:
public interface IPerson()
{
String FirstName { get; }
String LastName { get; }
Email EmailAddress { get; }
}
Then I would update my runtime Person class to implement the interface:
public class Person() : IPerson
{
public String FirstName { get; set;}
public String LastName {get; set;}
public Email EmailAddress {get; set;}
}
Then I would create a mock class that implements the same interface and provides sensible values for design time use
public MockPerson() : IPerson
{
public String FirstName { get { return "John"; } }
public String LastName { get { return "Smith"; } }
public Email EmailAddress { get { return new Email("John#smith.com"); } }
}
Then I would implement a mechanism to provide the MockPerson object at design time and the real Person object at runtime. Something like this or this. This provides design time data support without the hard dependency between the runtime and design time environments.
This pattern is much more flexible and will allow you to provide consistent design time data support throughout your application.

Possible to modify the C# that Linq To SQL generates?

It would be really handy to be able to somehow say that certain properties in the generated entity classes should, for example, be decorated by (say) validation attributes (as well as Linq To SQL column attributes).
Is it a T4 template someplace? Or are there other ways to skin the cat?
Damien Guard has written T4 templates that can be customized. See:
http://damieng.com/blog/2008/09/14/linq-to-sql-template-for-visual-studio-2008
...and:
http://visualstudiomagazine.com/listings/list.aspx?id=560
No, the SqlMetal tool is what handles the generation of the C# and it is defined within itself how the C# is generated (or VB for that matter).
I'm not familiar with the template style you want but you could try exteding the generated classes (if they aren't that big a change) since they are just partial classes.
Otherwise you would need to write/ look for a custom implementation of SqlMetal
Unfortunately, with partial classes you cannot add attributes to a member from another part of the partial class - i.e. if SqlMetal defines property Foo, you can't add an attribute to Foo in your own half of the .cs.
This takes away one of (usually) the more powerful ways of customizing such files... you would probably have to either take a chance and hand-edit the generated file (after detaching it from the dbml completely) - or write your own dbml parser frmo scratch (mayhbe using xslt). Not easy.
The workaround in Dynamic Data is by using a metadata class which can be decorated:
[MetadataType(typeof(Product_Meta))]
public partial class Product
{
public partial class Product_Meta
{
[Range(5, 50, ErrorMessage = "The product's reorder level must be greater than 5 and less than 50")]
public object ReorderLevel { get; set; }
}
}
http://rachelappel.com/asp-net-dynamic-data/custom-validation-in-asp-net-dynamic-data-using-attributes/

Categories

Resources