الإرشادات التفصيلية: إنشاء نوع جديد من قاعدة بيانات بحالة الأحرف لتغيير إلى Refacإلىring
في هذا الموضوع خطوة بخطوة، سيتم إنشاء، يثّبت، التسجيل، و اختبار نوع جديد من قاعدة بيانات إعادة بناء التعليمات البرمجية . سيتم تحويل هذه تشغيل إعادة بناء التعليمات البرمجية الحرف أول من اسم الكائن المحدد إلى أحرف كبيرة، ويقوم بتحديث الجميع المراجع إلى هذا الاسم المحدث.
توضح هذه الإرشادات التفصيلية المهام التالية:
قم بإنشاء تجميع جديدة التي تحتوي على فئات لنوع إعادة بناء التعليمات البرمجية مخصصة.
يثّبت و regهوter تجميع، حيث إعادة بناء التعليمات البرمجية كتابة هو المتوفرة في Visual Studio Premiumأو Visual Studio Ultimate.
قم بإنشاء على قاعدة بيانات مشروع بسيطة إلى اختبر نوع refacإلىring كما هو متوقع.
المتطلبات الأساسية
تحتاج إلى المكونات التالية لاستكمال هذه الإرشادات التفصيلية:
يجب تثبيت Visual Studio 2010 Premiumأو Visual Studio 2010 Ultimate.
يجب أن يكون لديك أيضا في Visual Studio 2010 تطوير مجموعة برامج (SDK) مثبتاً تشغيل جهاز الكمبيوتر الخاص بك. إلى ينزّل هذه المجموعة، راجع هذه الصفحة في موقع Microsoft Office 2010 Suite تشغيل ويب: SDK Visual Studio 2010.
إنشاء تجميع مع مخصص نوع إعادة بناء التعليمات البرمجية
لإنشاء نوع مخصص إعادة بناء التعليمات البرمجية يمكنها تحويل الحرف أول من اسم كائن إلى أحرف كبيرة و ثم تحديث الجميع المراجع إلى هذا الكائن، عليك تطبيق ست فئات:
CasingRefactoringCommand — Th هو قم بتوفير اسم الأمر لعرض قائمة refactoring فئة، ويحدد نوع refactoring الخاص بك تشغيل عناصر الطراز التي هو المتوفرة، وقم باستدعاء عملية إعادة بناء التعليمات البرمجية الخاص بك عندما ينقر مستخدم فوق الأمر.
Casingإعادة بناء التعليمات البرمجيةOperation-هذا فئة يحدد كيفية تفاعل تشغيل إعادة بناء التعليمات البرمجية الخاص بك باستخدام "نافذة معاينة" تعيين الخصائص التي تصف تشغيل ويقوم بإنشاء CasingContributorInput فئة.
CasingContributorInput-هذه الفئة بتخزين بيانات إدخال إلى فئة CasingSymbolContributor.
CasingSymbolContributor — Th هو فئة يبني lهوt عروض التم تغييره الخاص بالرمز الذي تمت إعادة تسميته، وكما يقوم بإنشاء الفئة CasingReferenceContributorInput لمعالجة جاري الآن التحديث المراجع إلى الكائن اسمه هو التم تغييره.
CasingReferenceContributorInput-هذه الفئة بتخزين بيانات إدخال إلى فئة CasingReferenceContributor.
CasingReferenceContributor-هذا فئة بناء قائمة مقترحات تغيير المقترنة بجاري الآن التحديث المراجع إلى الرمز الذي تمت إعادة تسميته.
قبل إنشاء هذه الفئات، يمكنك إنشاء مكتبة فئة، إضافة المطلوبة، و إضافة بعض تعليمات برمجية المساعد تسهل بعض تعليمات برمجية التي سيتم الكتابة فيما بعد في هذه معاينة.
إلى إنشاء رمز الفئة المكتبة والمساعد
إنشاء C# فئة مكتبة مشروع جديد و اسم من CasingRefactoringType.csproj.
إضافة مراجع إلى ما يلي فئة المكتبات:
Microsoft.بيانات.مخطط.dll
Microsoft.بيانات.مخطط.ScriptDom.dll
Microsoft.بيانات.مخطط.ScriptDom.sql.dll
Microsoft.بيانات.مخطط.Sql.dll
Microsoft.VisualStudio.بيانات.مخطط.حزمة.dll
Microsoft.VisualStudio.بيانات.مخطط.حزمة.Sql.dll
إضافة مراجع إلى تجميعات التالية من Visual Studio 2010 تطوير مجموعة برامج (SDK):
Microsoft.VisualStudio.OLE.Interop.dll
Microsoft.VisualStudio.Shell.10.0.dll
Microsoft.VisualStudio.Shell.Interop.dll
Microsoft.VisualStudio.Shell.Interop.8.0.dll
Microsoft.VisualStudio.Shell.Interop.9.0.dll
Microsoft.VisualStudio.Shell.Interop.10.0.dll
Microsoft.VisualStudio.TextManager.Interop.dll
من مستكشف الحل، إعادة تسمية Class1.cs إلى SampleHelper.cs.
انقر نقراً مزدوجاً لفتحه في تعليمات برمجية SampleHelper.cs محرر.
استبدال محتويات تعليمات برمجية محرر بالتعليمة البرمجية التالية:
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.ScriptDom.Sql; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring; using Microsoft.VisualStudio.Data.Schema.Package.UI; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.TextManager.Interop; namespace MySamples.Refactoring { internal static class SampleHelper { public static String GetModelElementName(IModelElement modelElement) { SampleHelper.CheckNullArgument(modelElement, "modelElement"); return modelElement.ToString(); } /// <summary> /// Given a model element, returns its simple name. /// </summary> public static String GetModelElementSimpleName(IModelElement modelElement) { String separator = "."; String simpleName = String.Empty; String fullName = modelElement.ToString(); String[] nameParts = fullName.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (nameParts.Length > 0) { simpleName = nameParts[nameParts.Length - 1]; // last part } if (simpleName.StartsWith("[") && simpleName.EndsWith("]")) { simpleName = simpleName.Substring(1, simpleName.Length - 2); } return simpleName; } /// <summary> /// Find all files in the project with the specified file extension /// </summary> public static List<string> GetAllFilesInProject(IVsHierarchy solutionNode, string fileExtension, bool visibleNodesOnly) { List<string> files = new List<string>(); if (null != solutionNode) { EnumProjectItems(solutionNode, fileExtension, files, VSConstants.VSITEMID_ROOT, // item id of solution root node 0, // recursion from solution node true, // hierarchy is Solution node visibleNodesOnly); // visibleNodesOnly } return files; } /// <summary> /// Enumerates recursively over the hierarchy items. /// </summary> /// <param name="hierarchy">hierarchy to enmerate over.</param> /// <param name="fileExtension">type of files we need to collect from the project</param> /// <param name="files">list of file paths</param> /// <param name="itemid">item id of the hierarchy</param> /// <param name="recursionLevel">Depth of recursion. e.g. if recursion started with the Solution /// node, then : Level 0 -- Solution node, Level 1 -- children of Solution, etc.</param> /// <param name="hierIsSolution">true if hierarchy is Solution Node. </param> /// <param name="visibleNodesOnly">true if only nodes visible in the Solution Explorer should /// be traversed. false if all project items should be traversed.</param> private static void EnumProjectItems(IVsHierarchy hierarchy, string fileExtension, List<string> files, uint itemid, int recursionLevel, bool hierIsSolution, bool visibleNodesOnly) { int hr; IntPtr nestedHierarchyObj; uint nestedItemId; Guid hierGuid = typeof(IVsHierarchy).GUID; // Check first if this node has a nested hierarchy. hr = hierarchy.GetNestedHierarchy(itemid, ref hierGuid, out nestedHierarchyObj, out nestedItemId); if (VSConstants.S_OK == hr && IntPtr.Zero != nestedHierarchyObj) { IVsHierarchy nestedHierarchy = Marshal.GetObjectForIUnknown(nestedHierarchyObj) as IVsHierarchy; Marshal.Release(nestedHierarchyObj); if (nestedHierarchy != null) { EnumProjectItems(nestedHierarchy, fileExtension, files, nestedItemId, recursionLevel, false, visibleNodesOnly); } } else { // Check if the file extension of this node matches string fileFullPath; hierarchy.GetCanonicalName(itemid, out fileFullPath); if (CompareExtension(fileFullPath, fileExtension)) { // add matched file paths into the list files.Add(fileFullPath); } recursionLevel++; //Get the first child node of the current hierarchy being walked object pVar; hr = hierarchy.GetProperty(itemid, ((visibleNodesOnly || (hierIsSolution && recursionLevel == 1) ? (int)__VSHPROPID.VSHPROPID_FirstVisibleChild : (int)__VSHPROPID.VSHPROPID_FirstChild)), out pVar); ErrorHandler.ThrowOnFailure(hr); if (VSConstants.S_OK == hr) { // Use Depth first search so at each level we recurse to check if the node has any children // and then look for siblings. uint childId = GetItemId(pVar); while (childId != VSConstants.VSITEMID_NIL) { EnumProjectItems(hierarchy, fileExtension, files, childId, recursionLevel, false, visibleNodesOnly); hr = hierarchy.GetProperty(childId, ((visibleNodesOnly || (hierIsSolution && recursionLevel == 1)) ? (int)__VSHPROPID.VSHPROPID_NextVisibleSibling : (int)__VSHPROPID.VSHPROPID_NextSibling), out pVar); if (VSConstants.S_OK == hr) { childId = GetItemId(pVar); } else { ErrorHandler.ThrowOnFailure(hr); break; } } } } } /// <summary> /// Gets the item id. /// </summary> /// <param name="pvar">VARIANT holding an itemid.</param> /// <returns>Item Id of the concerned node</returns> private static uint GetItemId(object pvar) { if (pvar == null) return VSConstants.VSITEMID_NIL; if (pvar is int) return (uint)(int)pvar; if (pvar is uint) return (uint)pvar; if (pvar is short) return (uint)(short)pvar; if (pvar is ushort) return (uint)(ushort)pvar; if (pvar is long) return (uint)(long)pvar; return VSConstants.VSITEMID_NIL; } /// <summary> /// Check if the file has the expected extension. /// </summary> /// <param name="filePath"></param> /// <param name="extension"></param> /// <returns></returns> public static bool CompareExtension(string filePath, string extension) { bool equals = false; if (!string.IsNullOrEmpty(filePath)) { equals = (string.Compare(System.IO.Path.GetExtension(filePath), extension, StringComparison.OrdinalIgnoreCase) == 0); } return equals; } /// <summary> /// Read file content from a file /// </summary> /// <param name="filePath"> file path </param> /// <returns> file content in a string </returns> internal static string ReadFileContent(string filePath) { // Ensure that the file exists first. if (!File.Exists(filePath)) { Debug.WriteLine(string.Format("Cannot find the file: '{0}'", filePath)); return string.Empty; } string content; using (StreamReader reader = new StreamReader(filePath)) { content = reader.ReadToEnd(); reader.Close(); } return content; } /// <summary> /// Check null references and throw /// </summary> /// <param name="obj"></param> /// <param name="?"></param> public static void CheckNullArgument(object obj, string objectName) { if (obj == null) { throw new System.ArgumentNullException(objectName); } } /// <summary> /// Get offset of the fragment from an Identifier if the identifier.value matches the /// name we are looking for. /// </summary> /// <param name="identifier"></param> /// <param name="expectedName"></param> public static RawChangeInfo AddOffsestFromIdentifier( Identifier identifier, String expectedName, String newName, Boolean keepOldQuote) { RawChangeInfo change = null; if (identifier != null && String.Compare(expectedName, identifier.Value, true) == 0) { if (keepOldQuote) { QuoteType newQuote = QuoteType.NotQuoted; newName = Identifier.DecodeIdentifier(newName, out newQuote); newName = Identifier.EncodeIdentifier(newName, identifier.QuoteType); } change = new RawChangeInfo(identifier.StartOffset, identifier.FragmentLength, expectedName, newName); } return change; } public static IList<ChangeProposal> ConvertOffsets( string projectFullName, string fileFullPath, List<RawChangeInfo> changes, bool defaultIncluded) { // Get the file content into IVsTextLines IVsTextLines textLines = GetTextLines(fileFullPath); int changesCount = changes.Count; List<ChangeProposal> changeProposals = new List<ChangeProposal>(changesCount); for (int changeIndex = 0; changeIndex < changesCount; changeIndex++) { int startLine = 0; int startColumn = 0; int endLine = 0; int endColumn = 0; RawChangeInfo currentChange = changes[changeIndex]; int startPosition = currentChange.StartOffset; int endPosition = currentChange.StartOffset + currentChange.Length; int result = textLines.GetLineIndexOfPosition(startPosition, out startLine, out startColumn); if (result == VSConstants.S_OK) { result = textLines.GetLineIndexOfPosition(endPosition, out endLine, out endColumn); if (result == VSConstants.S_OK) { TextChangeProposal changeProposal = new TextChangeProposal(projectFullName, fileFullPath, currentChange.NewText); changeProposal.StartLine = startLine; changeProposal.StartColumn = startColumn; changeProposal.EndLine = endLine; changeProposal.EndColumn = endColumn; changeProposal.Included = defaultIncluded; changeProposals.Add(changeProposal); } } if (result != VSConstants.S_OK) { throw new InvalidOperationException("Failed to convert offset"); } } return changeProposals; } /// <summary> /// Get IVsTextLines from a file. If that file is in RDT, get text buffer from it. /// If the file is not in RDT, open that file in invisible editor and get text buffer /// from it. /// If failed to get text buffer, it will return null. /// </summary> /// <param name="fullPathFileName">File name with full path.</param> /// <returns>Text buffer for that file.</returns> private static IVsTextLines GetTextLines(string fullPathFileName) { System.IServiceProvider serviceProvider = DataPackage.Instance; IVsTextLines textLines = null; IVsRunningDocumentTable rdt = (IVsRunningDocumentTable)serviceProvider.GetService(typeof(SVsRunningDocumentTable)); if (rdt != null) { IVsHierarchy ppHier = null; uint pitemid, pdwCookie; IntPtr ppunkDocData = IntPtr.Zero; try { rdt.FindAndLockDocument((uint)(_VSRDTFLAGS.RDT_NoLock), fullPathFileName, out ppHier, out pitemid, out ppunkDocData, out pdwCookie); if (pdwCookie != 0) { if (ppunkDocData != IntPtr.Zero) { try { // Get text lines from the doc data IVsPersistDocData docData = (IVsPersistDocData)Marshal.GetObjectForIUnknown(ppunkDocData); if (docData is IVsTextLines) { textLines = (IVsTextLines)docData; } else { textLines = null; } } catch (ArgumentException) { // Do nothing here, it will return null stream at the end. } } } else { // The file is not in RDT, open it in invisible editor and get the text lines from it. IVsInvisibleEditor invisibleEditor = null; TryGetTextLinesAndInvisibleEditor(fullPathFileName, out invisibleEditor, out textLines); } } finally { if (ppunkDocData != IntPtr.Zero) Marshal.Release(ppunkDocData); } } return textLines; } /// <summary> /// Open the file in invisible editor in the running /// documents table (RDT), and get text buffer from that editor. /// </summary> /// <param name="fullPathFileName">File name with full path.</param> /// <param name="spEditor">The result invisible editor.</param> /// <param name="textLines">The result text buffer.</param> /// <returns>True, if the file is opened correctly in invisible editor.</returns> private static bool TryGetTextLinesAndInvisibleEditor(string fullPathFileName, out IVsInvisibleEditor spEditor, out IVsTextLines textLines) { System.IServiceProvider serviceProvider = DataPackage.Instance; spEditor = null; textLines = null; // Need to open this file. Use the invisible editor manager to do so. IVsInvisibleEditorManager spIEM; IntPtr ppDocData = IntPtr.Zero; bool result; Guid IID_IVsTextLines = typeof(IVsTextLines).GUID; try { spIEM = (IVsInvisibleEditorManager)serviceProvider.GetService(typeof(IVsInvisibleEditorManager)); spIEM.RegisterInvisibleEditor(fullPathFileName, null, (uint)_EDITORREGFLAGS.RIEF_ENABLECACHING, null, out spEditor); if (spEditor != null) { int hr = spEditor.GetDocData(0, ref IID_IVsTextLines, out ppDocData); if (hr == VSConstants.S_OK && ppDocData != IntPtr.Zero) { textLines = Marshal.GetTypedObjectForIUnknown(ppDocData, typeof(IVsTextLines)) as IVsTextLines; result = true; } else { result = false; } } else { result = false; } } finally { if (ppDocData != IntPtr.Zero) Marshal.Release(ppDocData); } return result; } } }
تشغيل انقر قائمة ملف حفظ SampleHelper.cs.
إضافة فئة باسم RawChangeInfo إلى مشروع.
في تعليمات برمجية محرر، قم بتحديث تعليمات برمجية بحيث تتطابق مع ما يلي:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MySamples.Refactoring { /// <summary> /// Helper class to encapsulate StartOffset, FragmentLength and change string from /// parser and SchemaAnalzyer. /// </summary> internal sealed class RawChangeInfo { private int _startOffset; private int _length; private string _oldText; private string _newText; public RawChangeInfo(int startOffset, int length, string oldText, string newText) { _startOffset = startOffset; _length = length; _oldText = oldText; _newText = newText; } public int StartOffset { get { return _startOffset; } set { _startOffset = value; } } public int Length { get { return _length; } } public string OldText { get { return _oldText; } } public string NewText { get { return _newText; } set { _newText = value; } } } }
في قائمة ملف ، انقر فوق حفظ RawChangeInfo.cs.
بعد ذلك، سوف تقوم بتعريف CasingRefactoringCommand في فئة.
إلى تعريف الفئة CasingRefacإلىringCommand
إضافة فئة باسم CasingRefactorCommand إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using Microsoft.Data.Schema.Extensibility; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.SchemaModel.Abstract; using Microsoft.Data.Schema.Sql; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.VisualStudio.Data.Schema.Package.Project; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
[DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))] internal class CasingRefactorCommand : RefactoringSchemaViewNodeCommand { }
السمة هو المستخدمة لتعيين قاعدة بيانات مخطط موفري بأي ترتيب هو إعادة بناء التعليمات البرمجية نوع هو متوافقة. لترتيب هو المثال، نوع إعادة بناء التعليمات البرمجية الجديد ستعمل مع أي موفر التي هو مشتقة من SqlDatabaseSchemaProvider. الخاص بك فئة يرث RefactoringSchemaViewNodeCommand. يرث من القيم بالموضع هو فئة Base يشير إلى أن إعادة بناء التعليمات البرمجية نوع هو متوفرة تشغيل العقد المحدد في طريقة عرض المخطط. أنواع غير ذلك من إعادة بناء التعليمات البرمجية يمكن تعريف التي تعمل تشغيل ملف عقد و العقد للمشروع.
التالي، إضافة التالي يمنع أسلوب للفصل الدراسي:
public override void Execute(IDatabaseProjectNode currentProject, IModelElement selectedModelElement) { CasingRefactorOperation operation = new CasingRefactorOperation(currentProject, selectedModelElement); operation.DoOperation(); }
وهذا أسلوب يوفر سلوك عند تطبيق مستخدم الخاص بك الأمر إعادة بناء التعليمات البرمجية في طريقة عرض المخطط.
التالي، إضافة التالي يمنع أسلوب للفصل الدراسي:
public override QueryStatusResult QueryStatus(IModelElement selectedModelElement) { if (selectedModelElement is IDatabaseColumnSource || selectedModelElement is ISqlSimpleColumn || selectedModelElement is ISqlProcedure || selectedModelElement is ISqlFunction || selectedModelElement is ISqlIndex || selectedModelElement is ISqlConstraint) { return QueryStatusResult.Enabled; } else { return QueryStatusResult.Invisible; } }
Th هو يحدد أسلوب تشغيل أي العقد في طريقة عرض المخطط الخاص بك الأمر إعادة بناء التعليمات البرمجية هو المتوفرة.
وأخيراً، إضافة التالي يمنع أسلوب للفصل الدراسي:
public override string Text { get { return "Make First Letter Uppercase"; } }
وهذا أسلوب توفر الاسم المألوف للأمر إعادة بناء التعليمات البرمجية الذي يظهر في القائمة إعادة بناء التعليمات البرمجية.
تشغيل انقر قائمة ملف حفظ CasingRefactoringCommand.cs.
بعد ذلك، سوف تقوم بتعريف CasingRefactoringOperation في فئة.
إلى تعريف الفئة CasingRefacإلىringOperation
إضافة فئة باسم CasingRefactoringOperation إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using System; using System.Diagnostics; using System.Globalization; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.VisualStudio.Data.Schema.Package.Project; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
internal class CasingRefactorOperation : RefactoringOperation { }
الخاص بك فئة يجب أن يورث RefactoringOperation.
إضافة تعريفات المتغيرات ثابت والأعضاء التالية إلى الفصل الدراسي:
#region Const private const string CasingRefactorOperationName = @"Make First Letter Uppercase"; private const string OperationDescription = @"Make First Letter Uppercase"; private const string OperationTextViewDescription = @"Preview changes:"; private const string PreviewDialogTitle = @"Preview Changes - {0}"; private const string ConfirmButtonText = @"&Apply"; private const string CasingUndoDescription = @"Make first letter uppercase - {0}"; #endregion private string _operationName; private PreviewWindowInfo _previewWindowInfo; private ISqlModelElement _modelElement;
ثوابت خاصة بتوفير معلومات حول هذه تشغيل التي سيتم عرضها في نافذة معاينة.
إضافة الدالة الإنشائية الفئة:
public CasingRefactorOperation(IDatabaseProjectNode currentProject, IModelElement selectedModelElement) : base(currentProject) { _operationName = CasingRefactorOperationName; if (selectedModelElement as ISqlModelElement != null) { _modelElement = selectedModelElement as ISqlModelElement; } }
الدالة الإنشائية تهيئة اسم تشغيل وعنصر الطراز، إذا تم تعيين هذه.
يمنع PreviewWindowInfoالخاصية إلى الحصول على قيم التي تظهر في "نافذة المعاينة" عند تطبيق مستخدم الخاص بك نوع refacإلىring:
/// <summary> /// Preview dialog information for this RenameRefactorOperation. /// </summary> protected override PreviewWindowInfo PreviewWindowInfo { get { if (_previewWindowInfo == null) { _previewWindowInfo = new PreviewWindowInfo(); _previewWindowInfo.ConfirmButtonText = ConfirmButtonText; _previewWindowInfo.Description = OperationDescription; _previewWindowInfo.HelpContext = String.Empty; _previewWindowInfo.TextViewDescription = OperationTextViewDescription; _previewWindowInfo.Title = string.Format(CultureInfo.CurrentCulture,PreviewDialogTitle, CasingRefactorOperationName); } return _previewWindowInfo; } }
توفير ملفات تعريف الخصائص الإضافية:
protected override string OperationName { get { return _operationName; } } /// <summary> /// Undo Description used in undo stack /// </summary> protected override string UndoDescription { get { return string.Format(CultureInfo.CurrentCulture, CasingUndoDescription, SampleHelper.GetModelElementName(this.ModelElement)); } } /// <summary> /// SchemaIdentifier of currently selected schema object /// </summary> public ISqlModelElement ModelElement { get { return _modelElement; } set { _modelElement = value; } }
وأخيراً، يمنع OnGetContributorInputأسلوب:
/// <summary> /// According to different selected node, create different CasingContributorInput /// </summary> /// <returns></returns> protected override ContributorInput OnGetContributorInput() { ContributorInput input = null; SqlSchemaModel dataSchemaModel = this.CurrentDataSchemaModel as SqlSchemaModel; // You might choose to throw an exception here if // schemaModel is null. Debug.Assert(dataSchemaModel != null, "DataSchemaModel is null."); // create contributor input used in this operation input = new CasingContributorInput(this.ModelElement); return input; }
Th هو إنشاء أسلوب ContributorInputالتي هو التي تم تمريرها إلى المساهمين إعادة بناء التعليمات البرمجية لترتيب هو إعادة بناء التعليمات البرمجية نوع.
في قائمة ملف ، انقر فوق حفظ CasingRefactoringOperation.cs.
بعد ذلك، سوف تقوم بتعريف CasingContributorInput في فئة.
إلى تعريف الفئة CasingContribuإلىrInput
إضافة فئة باسم CasingContributorInput إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using System; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
internal class CasingContributorInput: ContributorInput { }
الخاص بك فئة يجب أن يورث ContributorInput.
قم بتعريف متغير عضو خاص إضافى:
private ISqlModelElement _modelElement;
يتم استخدام هذا العضو إلى التمكن من مقطع صوتي عنصر الطراز عند الذي كنت تعمل.
قم بإضافة الدالة الإنشائية الفئة:
public CasingContributorInput(ISqlModelElement modelElement) { _modelElement = modelElement; }
تهيئة المنشئ عنصر الطراز.
قم بإضافة خاصية القراءة فقط عام لعنصر الطراز:
/// <summary> /// Selected model element /// </summary> public ISqlModelElement ModelElement { get { return _modelElement; } }
يوفر أسلوب "يمنع يساوي" مقارنة التي تحدد ما إذا كان هناك كائنين CasingContributorInput كما هي:
/// <summary> /// Override Equals /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { CasingContributorInput other = obj as CasingContributorInput; return _modelElement.Equals(other.ModelElement); }
لهذا مساهم، الإدخالات سوف يتم التعامل مع نفس إذا كان يتم تطبيقها على عنصر الطراز نفسه.
يمنع في GetHashCode أسلوب:
/// <summary> /// Override GetHashCode /// </summary> /// <returns></returns> public override int GetHashCode() { Int32 hash = _modelElement.GetHashCode(); return hash; }
تشغيل انقر قائمة ملف حفظ CasingCتشغيلtributorInput.cs.
بعد ذلك، سوف تقوم بتعريف CasingSymbolContributor في فئة.
إلى تعريف الفئة CasingSymbolContribuإلىr
إضافة فئة باسم CasingSymbolContributor إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using Microsoft.Data.Schema.Extensibility; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.ScriptDom.Sql; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.Data.Schema.Sql; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
[DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))] internal class CasingSymbolContributor : RefactoringContributor<CasingContributorInput> { }
تعيين السمة للإعلان عن ذلك th هو مساهم هو متوافقة مع أية موفرات مخطط قاعدة بيانات المشتقة من SqlDatabaseSchemaProvider. يجب أن يورث الفئة من RefactoringContributorفئة. CasingContributorInput الخاص بك
قم بتعريف الثوابت الإضافية و متغيرات عضو خاص:
#region Const private const string PreviewGroupFriendlyName = @"Schema Objects"; private const string PreviewDescription = @"Uppercasing the first letter of schema object name and all references to this schema object."; private const string PreviewWarning = @"Changing casing of the schema object name may cause errors and warnings when your project is using case-sensitive collations. "; #endregion private RefactoringPreviewGroup _previewGroup;
الثوابت توفر المعلومات التي تظهر في "نافذة المعاينة". العضو إضافية هو يستخدم للاحتفاظ بتعقب مجموعة "المعاينة".
قم بإضافة الدالة الإنشائية الفئة:
#region ctor public CasingSymbolContributor() { _previewGroup = new RefactoringPreviewGroup(PreviewGroupFriendlyName); _previewGroup.Description = PreviewDescription; _previewGroup.WarningMessage = PreviewWarning; _previewGroup.EnableChangeGroupUncheck = false; _previewGroup.IncludeInCurrentProject = true; // the default icon will be used if do not register and icon for your file extensions //RefactoringPreviewGroup.RegisterIcon("sql", "SqlFileNode.ico"); //RefactoringPreviewGroup.RegisterIcon(".dbproj", "DatabaseProjectNode.ico"); // For some contributors, you might register a // language service here. //_previewGroup.RegisterLanguageService(".sql", ); base.RegisterGeneratedInputType(typeof(CasingReferenceContributorInput)); } #endregion
تهيئة المنشئ عنصر الطراز، قم بإنشاء مجموعة جديدة من معاينة وتهيئة الخصائص الخاصة به. يمكن أيضا تسجيل الرموز هنا ليتم عرضها في "نافذة المعاينة" للخاصة ملف ملحقات أسماء، ويمكن تسجيل الخدمة لغة التي يتم استخدامها لتوفير تلوين بناء الجملة ل ملف s التي تحتوي ملحق محدد.
يمنع PreviewGroupخاصية إلى بإرجاع مجموعة تم إنشاؤه عندما تم تاريخ الإنشاء هذا contribuإلىr:
#region overrides /// <summary> /// Preview group for schema object files /// </summary> public override RefactoringPreviewGroup PreviewGroup { get { return _previewGroup; } set { _previewGroup = value; } }
يمنع ContributeChangesأسلوب إلى إرجاع قائمة مقترحات تغيير:
/// <summary> /// Contribute to the change proposals /// </summary> /// <param name="input">contributor input</param> /// <returns>List of change proposals with corresponding contributor inputs</returns> protected override Tuple<IList<ChangeProposal>, IList<ContributorInput>> ContributeChanges(CasingContributorInput input) { CasingContributorInput casingInput = input as CasingContributorInput; if (casingInput == null) { throw new ArgumentNullException("input"); } string projectFullName; casingInput.RefactoringOperation.CurrentProjectHierarchy.GetCanonicalName(VSConstants.VSITEMID_ROOT, out projectFullName); Tuple<IList<ChangeProposal>, IList<ContributorInput>> changes = GetChangesFromCurrentSymbolScript( projectFullName, casingInput, casingInput.ModelElement, true); return changes; } #endregion
التالي، قم بإنشاء نوع آخر من ContributorInput:
/// <summary> /// Create a CasingReferenceContributorInput according to passed in CasingContributorInput /// </summary> /// <param name="orginalInput"></param> /// <returns></returns> internal ContributorInput CreateCasingReferenceInput(ContributorInput orginalInput) { CasingContributorInput casingInput = orginalInput as CasingContributorInput; Debug.Assert(casingInput != null, "casingInput is null"); CasingReferenceContributorInput referenceInput = new CasingReferenceContributorInput(casingInput.ModelElement); referenceInput.SchemaObjectsPreviewGroup = this.PreviewGroup; referenceInput.RefactoringOperation = casingInput.RefactoringOperation; return referenceInput; }
Th هو نوع إضافي من ContributorInputهو يستخدم لمعالجة الجميع المراجع إلى العنصر الذي تم تحديثه الرمز الخاص به. يمكن استدعاء هذا الأسلوب التالي الأسلوب.
إضافة أسلوب إلى بناء قائمة بالتغييرات الخاصة بالبرنامج النصي الذي يحتوي على تعريف الرمز الذي يتم refacإلىred:
public Tuple<IList<ChangeProposal>, IList<ContributorInput>> GetChangesFromCurrentSymbolScript( string projectFullName, ContributorInput input, ISqlModelElement modelElement, Boolean defaultChecked) { SampleHelper.CheckNullArgument(input, "input"); SampleHelper.CheckNullArgument(modelElement, "modelElement"); SqlSchemaModel dataSchemaModel = input.RefactoringOperation.CurrentDataSchemaModel as SqlSchemaModel; Debug.Assert(dataSchemaModel != null, "DataSchemaModel is null."); List<ChangeProposal> allChanges = new List<ChangeProposal>(); // list to hold all side effect contributor inputs List<ContributorInput> inputs = new List<ContributorInput>(); string fileFullPath = null; ISourceInformation elementSource = modelElement.PrimarySource; if (elementSource != null) { fileFullPath = elementSource.SourceName; } if (!string.IsNullOrEmpty(fileFullPath)) { List<RawChangeInfo> changes = AnalyzeScript(dataSchemaModel, modelElement); // Convert the offsets returned from parser to the line based offsets allChanges.AddRange(SampleHelper.ConvertOffsets(projectFullName, fileFullPath, changes, defaultChecked)); // Create a CasingReferenceContributorInput, anything reference this schema object // need to contribute changes for this input. inputs.Add(CreateCasingReferenceInput(input)); } return new Tuple<IList<ChangeProposal>, IList<ContributorInput>>(allChanges, inputs); }
هذا الأسلوب باستدعاء الأسلوب AnalyzeScript إلى معالجة العناصر برنامج نصي.
إضافة الأسلوب AnalyzeScript:
public static List<RawChangeInfo> AnalyzeScript(SqlSchemaModel dataSchemaModel, ISqlModelElement modelElement) { SampleHelper.CheckNullArgument(dataSchemaModel, "dataSchemaModel"); // get element source ISourceInformation elementSource = modelElement.PrimarySource; if (elementSource == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Cannot retrieve element source of {0}", SampleHelper.GetModelElementName(modelElement))); } // get sql fragment TSqlFragment fragment = elementSource.ScriptDom as TSqlFragment; if (fragment == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Cannot retrieve script fragment of {0}", SampleHelper.GetModelElementName(modelElement))); } List<RawChangeInfo> changes = new List<RawChangeInfo>(); Identifier id = null; if (fragment is CreateTableStatement) // Table { id = ((CreateTableStatement)fragment).SchemaObjectName.BaseIdentifier; } else if (fragment is CreateViewStatement) // View { id = ((CreateViewStatement)fragment).SchemaObjectName.BaseIdentifier; } else if (fragment is ColumnDefinition) // Column { id = ((ColumnDefinition)fragment).ColumnIdentifier; } else if (fragment is CreateProcedureStatement) // Proc { ProcedureReference procRef = ((CreateProcedureStatement)fragment).ProcedureReference; if (procRef != null) { id = procRef.Name.BaseIdentifier; } } else if (fragment is CreateFunctionStatement) // Function { id = ((CreateFunctionStatement)fragment).Name.BaseIdentifier; } else if (fragment is CreateIndexStatement) // Index { id = ((CreateIndexStatement)fragment).Name; } else if (fragment is Constraint) // inline constraint { id = ((Constraint)fragment).ConstraintIdentifier; } else if (fragment is AlterTableAddTableElementStatement) // default/check constraints { IList<Constraint> constraints = ((AlterTableAddTableElementStatement)fragment).TableConstraints; Debug.Assert(constraints.Count == 1, string.Format("Only one constraint expected, actual {0}", constraints.Count)); id = constraints[0].ConstraintIdentifier; } else // anything NYI { Debug.WriteLine(string.Format("Uppercasing symbol of type {0} is not implemented yet.", fragment.GetType().Name)); } string oldName = SampleHelper.GetModelElementSimpleName(modelElement); if (id != null && oldName.Length > 0) { string newName = oldName.Substring(0, 1).ToUpper() + oldName.Substring(1); // upper casing the first letter if (string.CompareOrdinal(oldName, newName) != 0) { RawChangeInfo change = SampleHelper.AddOffsestFromIdentifier(id, oldName, newName, true); if (change != null) { changes.Add(change); } } } return changes; }
وهذا أسلوب تكتسب مصدر برنامج نصي للعنصر الذي يتم refactored. أسلوب ثم يقوم باسترداد جزء SQL لهذا البرنامج المصدر. قم بإنشاء قائمة جديدة بتغيير الأسلوب ثم، قم بتحديد المعرف للعنصر (استناداً إلى نوع التجزئة)، و يضيف تغيير الجديد إلى قائمة التغييرات.
تشغيل انقر قائمة ملف حفظ CasingSymbolCتشغيلtributor.cs.
بعد ذلك، سوف تقوم بتعريف CasingReferenceContributorInput في فئة.
إلى تعريف الفئة CasingReferenceContribuإلىrInput
إضافة فئة باسم CasingReferenceContributorInput إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using System; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
internal class CasingReferenceContributorInput: ContributorInput { }
الخاص بك فئة يجب أن يورث ContributorInput.
قم بتعريف متغيرات عضو خاص إضافى:
private ISqlModelElement _modelElement; private RefactoringPreviewGroup _previewGroup;
يتم استخدام هؤلاء الأعضاء إلى الاحتفاظ بمقطع صوتي عنصر الطراز عند الذي كنت تعمل وفي المجموعة معاينة إلى التي تنتمي للتغييرات.
قم بإضافة الدالة الإنشائية الفئة:
public CasingReferenceContributorInput(ISqlModelElement modelElement) { _modelElement = modelElement; }
تهيئة المنشئ عنصر الطراز.
قم بإضافة خاصية القراءة فقط عام لعنصر الطراز:
/// <summary> /// Selected model element /// </summary> public ISqlModelElement ModelElement { get { return _modelElement; } }
قم بتعريف مجموعة معاينة إضافى للمعرفة من قبل مساهم هذه التغييرات:
/// <summary> /// Preview group that change proposals belong to /// </summary> public RefactoringPreviewGroup SchemaObjectsPreviewGroup { get { return _previewGroup; } set { _previewGroup = value; } }
يوفر أسلوب "يمنع يساوي" مقارنة التي تحدد ما إذا كان هناك كائنين CasingReferenceContributorInput كما هي:
/// <summary> /// Override Equals /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { CasingContributorInput other = obj as CasingContributorInput; return _modelElement.Equals(other.ModelElement); }
لهذا مساهم، الإدخالات سوف يتم التعامل مع نفس إذا كان يتم تطبيقها على عنصر الطراز نفسه.
يمنع في GetHashCode أسلوب:
/// <summary> /// Override GetHashCode /// </summary> /// <returns></returns> public override int GetHashCode() { Int32 hash = _modelElement.GetHashCode(); return hash; }
تشغيل انقر قائمة ملف حفظ CasingReferenceCتشغيلtributorInput.cs.
بعد ذلك، سوف تقوم بتعريف CasingReferenceContributor في فئة.
إلى تعريف الفئة CasingReferenceContribuإلىr
إضافة فئة باسم CasingReferenceContributor إلى مشروع.
في ediإلىr تعليمات برمجية، يتم تحديث استخدام عبارات إلى يطابق ما يلي:
using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Data.Schema.Extensibility; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.ScriptDom.Sql; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.Data.Schema.Sql; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Data.Schema.Package.Refactoring;
قم بتغيير مساحة الاسم إلى من MySamples.إعادة بناء التعليمات البرمجية:
namespace MySamples.Refactoring
قم بتحديث تعريف الفئة إلى يطابق ما يلي:
[DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))] internal class CasingReferenceContributor : RefactoringContributor<CasingReferenceContributorInput> { }
تعيين السمة للإعلان عن ذلك th هو مساهم هو متوافقة مع أية موفرات مخطط قاعدة بيانات المشتقة من SqlDatabaseSchemaProvider. يجب أن يورث الفئة من RefactoringContributorفئة. CasingReferenceContributorInput الخاص بك
قم بتعريف الثوابت الإضافية و متغيرات عضو خاص:
#region Const private const string PreviewGroupFriendlyName = @"Schema Objects"; private const string PreviewDescription = @"Uppercasing the name of this schema object and all references to this schema object."; private const string PreviewWarning = @"Changing casing of the schema object name may cause errors and warnings when your project is using case-sensitive collations. "; #endregion private RefactoringPreviewGroup _previewGroup;
الثوابت توفر المعلومات التي تظهر في "نافذة المعاينة". العضو إضافية هو يستخدم للاحتفاظ بتعقب مجموعة "المعاينة".
قم بإضافة الدالة الإنشائية الفئة:
public CasingReferenceContributor() { }
يمنع PreviewGroupخاصية إلى بإرجاع مجموعة تم إنشاؤه عندما تم تاريخ الإنشاء هذا contribuإلىr:
#region overrides /// <summary> /// Preview group for text files /// </summary> public override RefactoringPreviewGroup PreviewGroup { get { return _previewGroup; } set { _previewGroup = value; } } #endregion
يمنع ContributeChangesأسلوب إلى إرجاع قائمة مقترحات تغيير:
/// <summary> /// Contribute to the change proposals /// </summary> /// <param name="input">contributor input</param> /// <returns>List of change proposals with corresponding contributor inputs</returns> protected override Tuple<IList<ChangeProposal>, IList<ContributorInput>> ContributeChanges(CasingReferenceContributorInput input) { // cast input into reference input CasingReferenceContributorInput casingReferenceInput = input as CasingReferenceContributorInput; if (casingReferenceInput == null) { throw new ArgumentNullException("input"); } // Make sure CasingReferenceContributor and CasingSymbolContributor for a same refactoring operation // share the same preview group instance. if (casingReferenceInput.SchemaObjectsPreviewGroup != null) { _previewGroup = casingReferenceInput.SchemaObjectsPreviewGroup; } string projectFullName; casingReferenceInput.RefactoringOperation.CurrentProjectHierarchy.GetCanonicalName(VSConstants.VSITEMID_ROOT, out projectFullName); Tuple<IList<ChangeProposal>, IList<ContributorInput>> changes = GetChangesFromReferencedSymbolScripts( projectFullName, casingReferenceInput, casingReferenceInput.ModelElement, true ); return changes; }
ContributeChanges أسلوب GetChangesFromReferencedSymbolScripts يستدعي أسلوب.
تنفيذ الأسلوب GetChangesFromReferencedSymbolScripts إلى إرجاع قائمة مقترحات تغيير في برامج نصية التي تحتوي على مراجع إلى الرمز تحديث:
public static Tuple<IList<ChangeProposal>, IList<ContributorInput>> GetChangesFromReferencedSymbolScripts( string projectFullName, ContributorInput input, ISqlModelElement modelElement, bool defaultChecked // if the preview group is by default checked in the preview window ) { SampleHelper.CheckNullArgument(input, "input"); SqlSchemaModel dataSchemaModel = input.RefactoringOperation.CurrentDataSchemaModel as SqlSchemaModel; Debug.Assert(dataSchemaModel != null, "The DataSchemaModel is null for current Database project."); // Get all the changes for these schema objects that referencing the changed IModelElement. List<ChangeProposal> allChanges = new List<ChangeProposal>(); Dictionary<string, List<RawChangeInfo>> fileChanges = new Dictionary<string, List<RawChangeInfo>>(); List<RelationshipEntrySource> relationshipEntrySources = GetDependentEntries(dataSchemaModel, modelElement, true, true); foreach (var entry in relationshipEntrySources) { string fileFullPath = entry.Item1.SourceName; if (!string.IsNullOrEmpty(fileFullPath)) { IList<RawChangeInfo> result = AnalyzeRelationshipEntrySource(dataSchemaModel, modelElement, entry.Item2, entry.Item1); if (result != null) { List<RawChangeInfo> fileChange = null; if (!fileChanges.TryGetValue(fileFullPath, out fileChange)) { fileChange = new List<RawChangeInfo>(); fileChanges.Add(fileFullPath, fileChange); } fileChange.AddRange(result); } } } // Convert the offsets returned from ScriptDom to the line based offsets foreach (string fileFullPath in fileChanges.Keys) { allChanges.AddRange(SampleHelper.ConvertOffsets(projectFullName, fileFullPath, fileChanges[fileFullPath], defaultChecked)); } // Change propagation is not considered in this sample. // Thus the second value in the returned Tuple is set to null return new Tuple<IList<ChangeProposal>, IList<ContributorInput>>(allChanges, null); }
وهذا أسلوب يقوم باسترداد قائمة الجميع التبعيات الرمز المحدثة. يقوم باستدعاء الأسلوب AnalyzeRelationshipEntrySource ثم لكل مرجع إلى التعرف على أية تغييرات إضافى مطلوبة.
إضافة الأسلوب AnalyzeRelationshipEntrySource:
public static IList<RawChangeInfo> AnalyzeRelationshipEntrySource( SqlSchemaModel dataSchemaModel, ISqlModelElement modelElement, ISourceInformation relationshipEntrySource) { SampleHelper.CheckNullArgument(dataSchemaModel, "dataSchemaModel"); List<Identifier> identifiers = new List<Identifier>(); TSqlFragment fragment = relationshipEntrySource.ScriptDom as TSqlFragment; // handle expressions if (fragment is SelectColumn) { Expression exp = ((SelectColumn)fragment).Expression;// as Expression; fragment = exp as TSqlFragment; } else if (fragment is ExpressionWithSortOrder) { Expression exp = ((ExpressionWithSortOrder)fragment).Expression; // as Expression; fragment = exp as TSqlFragment; } else if (fragment is ExpressionGroupingSpecification) { Expression exp = ((ExpressionGroupingSpecification)fragment).Expression; // as Expression; fragment = exp as TSqlFragment; } // handle different fragment if (fragment is Identifier) { identifiers.Add((Identifier)fragment); ; } else if (fragment is Column) { identifiers.AddRange(((Column)fragment).Identifiers); } else if (fragment is ColumnWithSortOrder) { identifiers.Add(((ColumnWithSortOrder)fragment).ColumnIdentifier); } else if (fragment is SchemaObjectName) { identifiers.Add(((SchemaObjectName)fragment).BaseIdentifier); } else if (fragment is SchemaObjectTableSource) { identifiers.Add(((SchemaObjectTableSource)fragment).SchemaObject.BaseIdentifier); } else if (fragment is SchemaObjectDataModificationTarget) { identifiers.Add(((SchemaObjectDataModificationTarget)fragment).SchemaObject.BaseIdentifier); } else if (fragment is FunctionCall) { FunctionCall funcCall = (FunctionCall)fragment; IdentifiersCallTarget identsCallTarget = funcCall.CallTarget as IdentifiersCallTarget; if (identsCallTarget != null) { identifiers.AddRange(identsCallTarget.Identifiers); } identifiers.Add(funcCall.FunctionName); } else if (fragment is ProcedureReference) { SchemaObjectName procRefName = ((ProcedureReference)fragment).Name; if (procRefName != null) { identifiers.Add(procRefName.BaseIdentifier); } } else if (fragment is TriggerObject) { SchemaObjectName triggerName = ((TriggerObject)fragment).Name; if (triggerName != null) { identifiers.Add(triggerName.BaseIdentifier); } } else if (fragment is FullTextIndexColumn) { identifiers.Add(((FullTextIndexColumn)fragment).Name); } else if (fragment is SecurityTargetObject) { identifiers.AddRange(((SecurityTargetObject)fragment).ObjectName.Identifiers); } else // other types of fragments are not handled in this sample { Debug.WriteLine(string.Format("Uppercasing referencing object of type {0} is not implemented yet.", fragment.GetType().Name)); } List<RawChangeInfo> changes = new List<RawChangeInfo>(); string oldName = SampleHelper.GetModelElementSimpleName(modelElement); if (identifiers.Count > 0 && oldName.Length > 0) { string newName = oldName.Substring(0, 1).ToUpper() + oldName.Substring(1); // upper casing the first letter if (string.CompareOrdinal(oldName, newName) != 0) { // list of changes for this relationship entry RawChangeInfo change = null; foreach (Identifier idf in identifiers) { change = SampleHelper.AddOffsestFromIdentifier(idf, oldName, newName, true); if (change != null) { changes.Add(change); } } } } return changes; }
وهذا أسلوب يقوم باسترداد قائمة بالتغييرات التي يجب إجراؤها إلى أجزاء برنامج نصي الذي يعتمد تشغيل الرمز المحدثة.
أضف الأسلوب GetDependentEntries:
/// <summary> /// Get all relating relationship entries for the model element and its composing and hierarchical children /// </summary> internal static List<System.Tuple<ISourceInformation, IModelRelationshipEntry>> GetDependentEntries( SqlSchemaModel dataSchemaModel, ISqlModelElement modelElement, bool ignoreComposedRelationship, bool includeChildDependencies) { SampleHelper.CheckNullArgument(dataSchemaModel, "dataSchemaModel"); SampleHelper.CheckNullArgument(modelElement, "modelElement"); var dependencies = new List<System.Tuple<ISourceInformation, IModelRelationshipEntry>>(); List<IModelRelationshipEntry> relatingRelationships = new List<IModelRelationshipEntry>(); GetDependentEntries(modelElement, dataSchemaModel, new Dictionary<IModelElement, Object>(), relatingRelationships, includeChildDependencies); foreach (IModelRelationshipEntry entry in relatingRelationships) { ModelRelationshipType relationshipType = entry.RelationshipClass.ModelRelationshipType; if (!ignoreComposedRelationship || (relationshipType != ModelRelationshipType.Composing)) { ISqlModelElement relatingElement = entry.FromElement as ISqlModelElement; Debug.Assert(relatingElement != null, "Relating element got from ModelStore is null."); foreach (var si in relatingElement.GetRelationshipEntrySources(entry)) { dependencies.Add(new System.Tuple<ISourceInformation, IModelRelationshipEntry>(si, entry)); } } } return dependencies; } private static void GetDependentEntries( IModelElement modelElement, DataSchemaModel dataSchemaModel, Dictionary<IModelElement, Object> visitElement, List<IModelRelationshipEntry> relationshipEntries, Boolean includeChildDependencies) { if (modelElement != null && !visitElement.ContainsKey(modelElement)) { visitElement[modelElement] = null; IList<IModelRelationshipEntry> relatingRelationships = modelElement.GetReferencingRelationshipEntries(); relationshipEntries.AddRange(relatingRelationships); if (includeChildDependencies) { // First loop through all composed children of this element, and get their relationship entries as well foreach (IModelRelationshipEntry entry in modelElement.GetReferencedRelationshipEntries()) { if (entry.RelationshipClass.ModelRelationshipType == ModelRelationshipType.Composing) { GetDependentEntries(entry.Element, dataSchemaModel, visitElement, relationshipEntries, includeChildDependencies); } } // Then loop through all hierarchical children of this element, add their dependents to the list. foreach (IModelRelationshipEntry entry in relatingRelationships) { if (entry.RelationshipClass.ModelRelationshipType == ModelRelationshipType.Hierarchical) { GetDependentEntries(entry.FromElement, dataSchemaModel, visitElement, relationshipEntries, includeChildDependencies); } } } } }
تشغيل انقر قائمة ملف حفظ CasingReferenceCتشغيلtributor.cs.
التالي، سيتم تكوين وبنية تجميع.
إلى التسجيل وبنية تجميع
تشغيل انقر قائمة مشروع خصائص CasingRefactoringType.
انقر فوق علامة التبويب تسجيل الدخول.
انقر فوق توقيع تجميع.
في اختيار اسم المميز لمفاتيح ملف ، انقر فوق من <جديد>.
في إنشاء المفتاح اسم قوي صندوق حوار، في من اسم ملف المفتاح، اكتب من MyRefKey.
(اختياري) يمكنك تحديد كلمة مرور المفتاح الاسم المميز الخاص بك ملف.
انقر فوق موافق.
من القائمة ملف، انقر فوق حفظ الكل.
من القائمة Build (إنشاء)، انقر فوق Build Solution (إنشاء الحل).
بعد ذلك، يجب أن تقوم بتثبيت وتسجيل كـ sembly حيث يظهر كـ توفر اختبار شرط .
جاري التثبيت و تسجيل تجميع
إلى يثّبت تجميع CasingRefacإلىringType
قم بإنشاء مجلد باسم Myملحقات في المجلد% 10.0\VSTSDB\ملحقات ملفات%\Microsoft Visual Studio البرنامج.
قم بنسخ تجميع الموقعة (CasingRefactoringType.dll) إلى 10.0\VSTSDB\ملحقات\Myملحقات ملفات%\Microsoft برنامج Visual Studio% مجلد.
ملاحظة
ننصح بعدم نسخ ملفات XML الخاصة بك مباشرة في 10.0\VSTSDB\ملحقات Files%\Microsoft برنامج Visual Studio% مجلد. إذا كنت تستخدم مجلد فرعي بدلاً من ذلك، إلى منع التغييرات غير المقصودة غير ذلك الملفات المتوفرة مع Visual Studio.
بعد ذلك، يجب تسجيل تجميع الخاص بك، نوع من ملحق ميزة ، أنه سيظهر في Visual Studio.
إلى تسجيل تجميع CasingRefacإلىringType
قائمة عرض انقر فوق من Windows الأخرى، ومن ثم انقر فوق من نافذة الأوامر إلى فتح النافذة الأوامر.
في الإطار الأوامر، نوع التعليمة البرمجية التالية. ل FilePath، استبدل المسار و ملف اسم.dll المترجمة الخاصة بك ملف. تضمين علامات الاقتباس حول المسار و ملف اسم.
ملاحظة
بشكل افتراضي، مسار ملف.dll المترجمة الخاصة بك هو\bin\يصحح YourSolutionPath أو\bin\يطرح المنتج YourSolutionPath .
? System.Reflection.Assembly.LoadFrom("FilePath").FullName
? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
اضغط Enter.
قم بنسخ خط الناتجة إلى "حافظة". يجب على الخط لما يلي:
"GeneratorAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
افتح محرر نص عادي، مثل المفكرة كـ.
هام
في Windows Vistaو Microsoft Office 2010 Suite نظام التشغيل Windows الخادم 2008، فتح محرر كمسؤول حتى يمكنك حفظ ملف برنامج ملف s المجلد.
قم بتوفير المعلومات التالية، قم بتحديد اسم التجميع الخاص بك، ورمز مفتاح عام، و نوع الملحق:
<?xml version="1.0" encoding="utf-8" ?> <extensions assembly="" version="1" xmlns="urn:Microsoft.Data.Schema.Extensions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:Microsoft.Data.Schema.Extensions Microsoft.Data.Schema.Extensions.xsd"> <extension type="MySamples.Refactoring.CasingRefactorCommand" assembly=" CasingRefactoringType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<enter key here>" enabled="true" /> <extension type="MySamples.Refactoring.CasingSymbolContributor" assembly="CasingRefactoringType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<enter key here>" enabled="true" /> <extension type="MySamples.Refactoring.CasingReferenceContributor" assembly="CasingRefactoringType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<enter key here>" enabled="true" /> </extensions>
يمكنك استخدام ملف XML هذا إلى تسجيل الفئة التي ترث من RefactoringCommandوالفئات ذات الصلة التي تنتج من RefactoringContributor.
قم بحفظ الملف ك CasingRefactoringType.ملحقات.xml في المجلد% 10.0\VSTSDB\ملحقات\MyExtensions ملفات%\Microsoft برنامج Visual Studio.
قم بإغلاق Visual Studio.
بعد ذلك، ستقوم بإنشاء مشروع قاعدة بيانات بسيطة جداً إلى اختبار نوع refacإلىring الجديد.
اختبار نوع إعادة بناء التعليمات البرمجية جديد
إلى إنشاء مشروع قاعدة بيانات
في قائمة ملف ، أشر إلى من جديد و انقر فوق مشروع.
تحت المتوقعة القوالب المثبتة و العقدة قاعدة بيانات، و انقر فوق العقدة SQL الخادم.
في قائمة القوالب، انقر فوق مشروع قاعدة بيانات في SQL الخادم 2008.
انقر فوق موافق إلى قبول اسم مشروع الافتراضي وقم بإنشاء مشروع.
يتم تاريخ الإنشاء مشروع قاعدة بيانات فارغ.
إلى إضافة جدول مع المفتاح أساسي
في قائمة عرض ، انقر فوق عرض مخطط قاعدة بيانات.
في طريقة عرض المخطط، توسيع العقدة رسوم تخطيطية توسيع العقدة dbo ، انقر نقراً مزدوجاً فوق عقدة جداول ، أشر إلى إضافةوانقر فوق جدول.
في صندوق الحوار الخاص ب إضافة عنصر جديد? ، في الاسم، اكتب الموظفين .
ملاحظة
عن قصد استخدام أحرف صغيرة للبدء في اسم الجدول.
انقر فوق موافق.
قم بتوسيع العقدة جداول ، يمين-انقر فوق العقدة الموظف ، أشر إلى إضافةوانقر فوق من المفتاح أساسي.
في إضافة عنصر جديد? صندوق حوار، في الاسم، اكتب من PK_Employee_column_1.
انقر فوق موافق.
بعد ذلك، سيتم استخدام نوع refacإلىring الجديد إلى تغيير الجدول اسم وكافة المراجع إلى عليه.
لاستخدام جديد إعادة بناء التعليمات البرمجية نوع تحديث اسم الجدول
في عرض مخطط، انقر نقراً مزدوجاً فوق عقدة جدول الموظفين، وأشر إلى إعادة بناء التعليمات البرمجية، وانقر فوق إنشاء اﻷول رسالة كبيرة.
تعريف هذا النوع الجديد من إعادة بناء التعليمات البرمجية في هذه معاينة.
في صندوق الحوار معاينة التغييرات ، قم بمراجعة التغييرات، و ثم انقر فوق يطبق.
اسم الجدول هو محدث بحيث يمكن للموظفين. مرجع إلى الجدول في المفتاح أساسي هو أيضا محدث.
الخطوات التالية
يمكنك إنشاء أنواع إضافى من إعادة تأهيل قاعدة بيانات. يمكنك أيضا إضافة مزيد من contribuإلىrs إلى تمكين نوع موجود لقاعدة بيانات refacإلىring إلى تعمل تشغيل أنواع إضافى من الملفات أو الكائنات.
راجع أيضًا:
المهام
الإرشادات التفصيلية: توسيع قاعدة بيانات إعادة تسمية Refacإلىring إلى تشغيلها في ملفات نصية