Rank: Advanced Member Groups: Member
Joined: 4/24/2008 Posts: 6 Points: 18 Location: Scotland
|
Heres a command that takes a method and builds the delegates and Begin/End methods that allow it to be ran using the APM. Use the 'async' command anywhere inside the method. C# Code: <?xml version="1.0"?> <Commands xmlns="http://schemas.devprojects.net/AutoCode/v3.0"> <Command name="MethodToAsync" priority="100">
<CommandBehavior> <CommandLine shortcut="async" /> <ActiveDocument extensions=".cs"/> </CommandBehavior>
<CommandInfo> <LanguageCategory>CSharp</LanguageCategory> <Category>Members/Methods</Category> <Usage> <![CDATA[async]]> </Usage> <Description>Creates the delegates and Begin & End methods needed for a method to support the APM. Only instance methods are supported.</Description> <Author>Derek Smyth</Author> <HelpUrl>http://www.dsmyth.net/wiki</HelpUrl> </CommandInfo>
<CommandCode language="csharp"> <Render> //string builder will build some code System.Text.StringBuilder buildr = new StringBuilder(); //get the method that the current point is in CodeFunction cf = (CodeFunction) Selection.ActivePoint.get_CodeElement(vsCMElement.vsCMElementFunction); //if the method if function or sub if (cf.FunctionKind == vsCMFunction.vsCMFunctionFunction || cf.FunctionKind == vsCMFunction.vsCMFunctionSub) { //get the code element CodeElement ce = GetCodeElement(CodeElementTypes.Function); TextPoint cp = ce.EndPoint; Selection.MoveToPoint(cp, false); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("#region APM Methods for " + cf.Name); buildr.Append("\r\n"); buildr.Append("\r\n"); //declare the delegate prototype CodeTypeRef functionType = (CodeTypeRef)cf.Type; buildr.Append("private delegate " + functionType.AsString + " Delegate" + cf.Name + "("); foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append(paramType.AsString + " " + param.Name + ", "); } if (buildr.ToString().EndsWith(",")) { buildr.Remove(buildr.Length - 1, 1); } buildr.Append(");"); buildr.Append("\r\n"); buildr.Append("private Delegate" + cf.Name + " " + cf.Name + "DelegateInstance;"); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("public IAsyncResult Begin" + cf.Name + "("); foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append(paramType.AsString + " " + param.Name + ", "); } buildr.Append("AsyncCallback DelegateCallback, "); buildr.Append("object DelegateAsyncState"); buildr.Append(")"); buildr.Append("\r\n"); buildr.Append("{"); buildr.Append("\r\n"); buildr.Append("if(" + cf.Name + "DelegateInstance == null)"); buildr.Append("\r\n"); buildr.Append(cf.Name + "DelegateInstance = new Delegate" + cf.Name +"(" + cf.Name + ");"); buildr.Append("\r\n"); buildr.Append("return "+ cf.Name + "DelegateInstance.BeginInvoke(");
foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append(param.Name + ", "); } buildr.Append("DelegateCallback, "); buildr.Append("DelegateAsyncState"); buildr.Append(");"); buildr.Append("\r\n"); buildr.Append("}"); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("public " + functionType.AsString + " End" + cf.Name + "(IAsyncResult result)"); buildr.Append("\r\n"); buildr.Append("{"); buildr.Append("\r\n"); if (functionType.AsString == "void") buildr.Append(cf.Name + "DelegateInstance.EndInvoke(result);"); else buildr.Append("return "+ cf.Name + "DelegateInstance.EndInvoke(result);"); buildr.Append("\r\n"); buildr.Append("}"); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("#endregion"); }
Selection.Text = buildr.ToString(); </Render>
<SmartFormat> <Start codeElement="Document" codePoint="StartOfElement" /> <End codeElement="Document" codePoint="EndOfElement" /> </SmartFormat> </CommandCode> </Command>
</Commands>
VB.NET Code: <?xml version="1.0"?> <Commands xmlns="http://schemas.devprojects.net/AutoCode/v3.0"> <Command name="MethodToAsync" priority="100">
<CommandBehavior> <CommandLine shortcut="async" /> <ActiveDocument extensions=".vb"/> </CommandBehavior>
<CommandInfo> <LanguageCategory>VB.NET</LanguageCategory> <Category>Members/Methods</Category> <Usage> <![CDATA[async]]> </Usage> <Description>Creates the delegates and Begin & End methods needed for a method to support the APM. Only instance methods are supported.</Description> <Author>Derek Smyth</Author> <HelpUrl>http://www.dsmyth.net/wiki</HelpUrl> </CommandInfo>
<CommandCode language="csharp"> <Render> //string builder will build some code System.Text.StringBuilder buildr = new StringBuilder(); //get the method that the current point is in CodeFunction cf = (CodeFunction) Selection.ActivePoint.get_CodeElement(vsCMElement.vsCMElementFunction); //get the code element CodeElement ce = GetCodeElement(CodeElementTypes.Function); TextPoint cp = ce.EndPoint; Selection.MoveToPoint(cp, false); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("#Region \"APM Methods for " + cf.Name + "\""); buildr.Append("\r\n"); buildr.Append("\r\n"); CodeTypeRef functionType = (CodeTypeRef)cf.Type; if (cf.FunctionKind == vsCMFunction.vsCMFunctionFunction) { //declare the delegate prototype; function buildr.Append("Private Delegate Function " + cf.Name + "Delegate("); foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append("ByVal " + param.Name + " As " + paramType.AsString + ", "); } buildr.Remove(buildr.Length - 2, 1); buildr.Append(") As " + functionType.AsString); } else if(cf.FunctionKind == vsCMFunction.vsCMFunctionSub) { //declare the delegate prototype; Sub buildr.Append("Private Delegate Sub " + cf.Name + "Delegate("); foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append("ByVal " + param.Name + " As " + paramType.AsString + ", "); } buildr.Remove(buildr.Length - 2, 1); buildr.Append(")"); }
buildr.Append("\r\n"); buildr.Append("Private " + cf.Name + "DelegateInstance As New " + cf.Name + "Delegate(AddressOf " + cf.Name + ")"); buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("Public Function Begin" + cf.Name + "("); foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append("ByVal " + param.Name + " As " + paramType.AsString + ", "); } buildr.Append("ByVal DelegateCallback As AsyncCallback, "); buildr.Append("ByVal DelegateAsyncState As Object"); buildr.Append(") As IAsyncResult"); buildr.Append("\r\n"); buildr.Append("Return "+ cf.Name + "DelegateInstance.BeginInvoke(");
foreach(CodeParameter param in cf.Parameters) { CodeTypeRef paramType = (CodeTypeRef)param.Type; buildr.Append(param.Name + ", "); } buildr.Append("DelegateCallback, "); buildr.Append("DelegateAsyncState"); buildr.Append(")"); buildr.Append("\r\n"); buildr.Append("End Function"); buildr.Append("\r\n"); buildr.Append("\r\n"); if (cf.FunctionKind == vsCMFunction.vsCMFunctionFunction) { buildr.Append("Public Function End" + cf.Name + "(ByVal result As IAsyncResult) As " + functionType.AsString); buildr.Append("\r\n"); buildr.Append("Return "+ cf.Name + "DelegateInstance.EndInvoke(result)"); buildr.Append("\r\n"); buildr.Append("End Function"); } else if(cf.FunctionKind == vsCMFunction.vsCMFunctionSub) { buildr.Append("Public Sub End" + cf.Name + "(ByVal result As IAsyncResult)"); buildr.Append("\r\n"); buildr.Append(cf.Name + "DelegateInstance.EndInvoke(result)"); buildr.Append("\r\n"); buildr.Append("End Sub"); } buildr.Append("\r\n"); buildr.Append("\r\n"); buildr.Append("#End Region");
Selection.Text = buildr.ToString(); </Render>
</CommandCode> </Command>
</Commands>
Let me know if you have any problems with it.
|
Rank: Administration Groups: Administration
Joined: 3/16/2008 Posts: 22 Points: 72 Location: Spain
|
It works perfect! And it’s a very interesting one, not just because it shows how to access the CodeModel, but also because it shows how to create an async method. These are one of those patterns that take you a while to find when you need it. I always forget exactly how to implement typical patterns as writing an event or how to serialize a class and need to do a search to remember, so having it done just executing a command is very time saving. By the way, I took a look at your site http://www.dsmyth.net/wiki and found it a very interesting place for .net resources I have already bookmarked. Great work! Thanks, Alvaro
|