The assigned values of code model elements, such as classes, structs, functions, attributes, delegates, and so forth, may change after you make certain kinds of edits. Consequently, you cannot assume that the values will remain static.
If you assign a code model element to a local variable, for example, and you then set a property value for this local variable, the local variable may not contain a valid code model element when you reference it later. In fact, it may even contain a different code model element.
Consider a class containing a function named "MyFunction" which is assigned to a CodeFunction variable, and then the Name property of the CodeFunction is set to the value "YourFunction." After this variable assignment, you are no longer guaranteed that your local variable represents the same CodeFunction. Subsequently, accessing the value of the property may return E_FAIL as a result.
The recommended approach for dealing with this situation is to explicitly reassign your local variable to the correct code model element before accessing its property values. The following shows an example of how to do this. (The code is in the form of an add-in.)
Description
Code
[Visual Basic]
Public Sub OnConnection(ByVal application As Object, ByVal _
connectMode As ext_ConnectMode, ByVal addInInst As Object, _
ByRef custom As Array) Implements IDTExtensibility2.OnConnection
_applicationObject = CType(application, DTE2)
_addInInstance = CType(addInInst, AddIn)
ReassignValue(_applicationObject)
End Sub
Sub ReassignValue(ByVal dte As DTE2)
' Before running, create a new Windows application project,
' and then add a function to it named MyFunction.
Try
Dim myFCM As FileCodeModel = _
dte.ActiveDocument.ProjectItem.FileCodeModel
' Change the MyFunction name in Form1 class to
' the name, OtherFunction.
Dim myClass1 As CodeClass = _
CType(myFCM.CodeElements.Item("Form1"), CodeClass2)
Dim myFunction As CodeFunction = _
CType(myClass1.Members.Item("MyFunction"), CodeFunction2)
myFunction.Name = "OtherFunction"
myFunction = CType(myClass1.Members.Item("OtherFunction"), _
CodeFunction2)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
[C#]
public void OnConnection(object application, ext_ConnectMode
connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
ReassignValue(_applicationObject);
}
// Before running, create a new Windows application project,
// and then add a function to it named MyFunction.
public void ReassignValue(DTE2 dte)
{
try
{
FileCodeModel myFCM =
dte.ActiveDocument.ProjectItem.FileCodeModel;
// Change the MyFunction name in Form1 class to
// the name, OtherFunction.
CodeClass myClass1 =
(CodeClass2)myFCM.CodeElements.Item("Form1");
CodeFunction myFunction =
(CodeFunction2)myClass1.Members.Item("MyFunction");
myFunction.Name = "OtherFunction";
myFunction =
(CodeFunction2)myClass1.Members.Item("OtherFunction");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
Note: |
|---|
Setting the properties of child elements of your code model element does not exhibit this behavior. Only properties that directly affect the CodeElement — such as the name of the element, the type of a function, the signature of a method, etc. — exhibit this non-deterministic behavior. Also, this example works only if the new name of the CodeElement is unique among its siblings. This is because the Item property returns the first match, which does not work for overloaded methods/properties, partial classes, or namespaces with the same name. |