using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace SilverlightWebService

{

public partial class WebForm1 : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

DateTime dt = DateTime.Now.AddDays(-10);

Response.Write("오늘날짜보다 10일전:"+dt.ToShortDateString()+"<br>");

TimeSpan ts = DateTime.Now.Subtract(dt);

double d= ts.TotalDays;

Response.Write("날짜차이간격:"+d.ToString());

}

}

갑자기 VS 2005 가 실행이 안되었따;;;

검색해보니깐 Termial Services 서비스를 작동시키란다

image

 

 

image

오류는 해결됐따;;; 근데 터미널 서비스랑 무슨 상관인지?????

Termial Services...

클라이언트 장치가 서버에서 실행 중인 가상의 Windows 2000 Professional 데스크톱 세션 및 Windows 기반의 프로그램을 액세스할 수 있도록, 다중 세션 환경을 제공합니다.

매개 변수
method

args 매개 변수에 있는 매개 변수의 수 및 형식과 동일한 매개 변수를 갖는 메서드의 대리자입니다.

args

지정된 메서드에 인수로 전달하는 개체의 배열입니다. 메서드가 인수를 사용하지 않으면 이 매개 변수는 Null 참조(Visual Basic의 경우 Nothing)이 될 수 있습니다.

반환 값

호출되는 대리자의 반환 값이 들어 있는 Object이거나, 대리자에 반환 값이 없으면 Null 참조(Visual Basic의 경우 Nothing)입니다.

설명

대리자는 C 또는 C++ 언어의 함수 포인터와 유사합니다. 대리자는 대리자 개체 안에서 메서드에 대한 참조를 캡슐화합니다. 이 대리자 개체는 참조된 메서드를 호출하는 코드로 전달될 수 있으며 컴파일 타임에는 호출될 메서드를 알 수 없습니다. C 또는 C++의 함수 포인터와 달리 대리자는 개체 지향적이고 형식이 보다 안전합니다.

컨트롤의 핸들이 없으면 이 메서드는 창 핸들이 있는 컨트롤이나 폼을 찾을 때까지 해당 컨트롤의 부모 체인을 위로 검색합니다. 적절한 핸들을 찾을 수 없으면 이 메서드는 예외를 throw합니다. 호출자에 호출을 콜백하는 동안 발생하는 예외입니다.

참고

컨트롤에는 InvokeRequired 속성과 함께 스레드로부터 안전한 네 개의 메서드(Invoke, BeginInvoke, EndInvoke, CreateGraphics)가 있습니다. 다른 스레드에서 메서드를 호출하는 경우 이러한 호출 메서드 중 하나를 사용하여 컨트롤의 스레드에 대한 호출을 마샬링해야 합니다.

대리자는 EventHandler의 인스턴스가 될 수 있습니다. 이 경우 송신자 매개 변수가 이 컨트롤을 포함하고, 이벤트 매개 변수가 EventArgs.Empty를 포함합니다. 또한 대리자는 MethodInvoker의 인스턴스가 되거나, void 매개 변수 목록을 사용하는 다른 대리자가 될 수 있습니다. EventHandlerMethodInvoker 대리자는 다른 형식의 대리자보다 빨리 호출됩니다.

참고

메시지를 처리해야 하는 스레드가 더 이상 활성 상태가 아니면 예외가 throw될 수 있습니다.

Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows CE 플랫폼 참고: .NET Compact Framework 응용 프로그램에서는 대리자가 EventHandler의 인스턴스여야 합니다. 예제를 보려면 대리자 샘플을 참조하십시오.

다음 코드 예제에서는 대리자가 들어 있는 컨트롤을 보여 줍니다. 대리자는 목록 상자에 항목을 추가하는 메서드를 캡슐화하고 이 메서드는 지정한 인수를 통해 폼의 내부 핸들을 소유하는 스레드에서 실행됩니다. 사용자가 단추를 클릭하면 Invoke가 대리자를 실행합니다.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

   public class MyFormControl : Form
   {
      public delegate void AddListItem(String myString);
      public AddListItem myDelegate;
      private Button myButton;
      private Thread myThread;
      private ListBox myListBox;
      public MyFormControl()
      {
         myButton = new Button();
         myListBox = new ListBox();
         myButton.Location = new Point(72, 160);
         myButton.Size = new Size(152, 32);
         myButton.TabIndex = 1;
         myButton.Text = "Add items in list box";
         myButton.Click += new EventHandler(Button_Click);
         myListBox.Location = new Point(48, 32);
         myListBox.Name = "myListBox";
         myListBox.Size = new Size(200, 95);
         myListBox.TabIndex = 2;
         ClientSize = new Size(292, 273);
         Controls.AddRange(new Control[] {myListBox,myButton});
         Text = " 'Control_Invoke' example ";
         myDelegate = new AddListItem(AddListItemMethod);
      }
      static void Main()
      {
         MyFormControl myForm = new MyFormControl();
         myForm.ShowDialog();
      }
      public void AddListItemMethod(String myString)
      {
            myListBox.Items.Add(myString);
      }
      private void Button_Click(object sender, EventArgs e)
      {
         myThread = new Thread(new ThreadStart(ThreadFunction));
         myThread.Start();
      }
      private void ThreadFunction()
      {
         MyThreadClass myThreadClassObject  = new MyThreadClass(this);
         myThreadClassObject.Run();
      }
   }
   public class MyThreadClass
   {
      MyFormControl myFormControl1;
      public MyThreadClass(MyFormControl myForm)
      {
         myFormControl1 = myForm;
      }
      String myString;

      public void Run()
      {

         for (int i = 1; i <= 5; i++)
         {
            myString = "Step number " + i.ToString() + " executed";
            Thread.Sleep(400);
            // Execute the specified delegate on the thread that owns
            // 'myFormControl1' control's underlying window handle with
            // the specified list of arguments.
            myFormControl1.Invoke(myFormControl1.myDelegate,
                                   new Object[] {myString});
         }
      }
   }

참고 URL

http://support.microsoft.com/kb/307010/ko

Md5

http://www.hoons.kr/Lectureview.aspx?key=Lecture&LECCATE_IDX=26&ref=1&lecture_idx=45

http://msdn2.microsoft.com/ko-kr/library/system.security.cryptography.md5(VS.80).aspx#Mtps_DropDownFilterText

SHA1

http://msdn2.microsoft.com/ko-kr/library/system.security.cryptography.sha1(VS.80).aspx

MD5 클래스

MD5 해시 알고리즘의 모든 구현이 상속될 추상 클래스를 나타냅니다.

네임스페이스: System.Security.Cryptography
어셈블리: mscorlib(mscorlib.dll)

해시 함수는 임의의 길이의 이진 문자열을 고정된 길이의 작은 이진 문자열에 매핑합니다. 암호화 해시 함수는 동일한 값에 해시하는 두 개의 다른 입력을 연산적으로 찾지 못하는 속성, 즉 해당 데이터가 일치하면 두 집합의 데이터 해시도 일치하는 속성을 갖습니다. 데이터에 작은 변경이 있으면 해시에 예측할 수 없는 커다란 변경이 발생합니다.

MD5 알고리즘에 대한 해시 크기는 128비트입니다.

MD5 클래스의 :Track('ctl00_rs1_mainContentContainer_cpe58026_c|ctl00_rs1_mainContentContainer_ctl20',this);" href="http://msdn2.microsoft.com/ko-kr/library/tessz10c(VS.80).aspx">ComputeHash 메서드는 해시를 16바이트 배열로 반환합니다. 일부 MD5 구현에서는 32자로 된 16진수 형식의 해시를 생성합니다. 이러한 구현을 사용하려면 ComputeHash 메서드의 반환 값 형식을 16진수 값으로 지정합니다.

 

 

예제

다음 코드 예제에서는 문자열의 MD5 해시 값을 계산하고 해시를 32자로 된 16진수 형식의 문자열로 반환합니다. 이 코드 예제에서 만든 해시 문자열은 모든 플랫폼에서 32자로 된 16진수 형식의 해시 문자열을 만드는 모든 MD5 해시 함수와 호환됩니다

using System;
using System.Security.Cryptography;
using System.Text;

class Example
{
    // Hash an input string and return the hash as
    // a 32 character hexadecimal string.
    static string getMd5Hash(string input)
    {
// Create a new instance of the MD5CryptoServiceProvider object.
        MD5 md5Hasher = MD5.Create();

  // Convert the input string to a byte array and compute the hash.
        byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));

// Create a new Stringbuilder to collect the bytes
        // and create a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop through each byte of the hashed data
        // and format each one as a hexadecimal string.
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

     // Return the hexadecimal string.
        return sBuilder.ToString();
    }

// Verify a hash against a string.
    static bool verifyMd5Hash(string input, string hash)
    {
// Hash the input.
        string hashOfInput = getMd5Hash(input);

  // Create a StringComparer an comare the hashes.
        StringComparer comparer = StringComparer.OrdinalIgnoreCase;

        if (0 == comparer.Compare(hashOfInput, hash))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    static void Main()
    {
        string source = "Hello World!";
        string hash = getMd5Hash(source);

        Console.WriteLine("The MD5 hash of " + source + " is: " + hash + ".");

        Console.WriteLine("Verifying the hash...");

        if (verifyMd5Hash(source, hash))
        {
            Console.WriteLine("The hashes are the same.");
        }
        else
        {
            Console.WriteLine("The hashes are not same.");
        }
    }
}

// This code example produces the following output:
//
// The MD5 hash of Hello World! is: ed076287532e86365e841e92bfc50d8c.
// Verifying the hash...
// The hashes are the same.

-----------------------------------------------------------------------------------------

            string hashedPassword =

               FormsAuthentication.HashPasswordForStoringInConfigFile(password.Text, "MD5");

Response.Write(hashedPassword)

          -----------------------------------------------------------------------------------

            MD5 md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(this.password.Text));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
Response.Write("<br>md5Hasher=" + sBuilder.ToString().ToUpper() );

위의 두개는 결과값이 같습니다. 편한걸로 쓰세요

SHA1 클래스

입력 데이터에 대한 SHA1 해시를 계산합니다.

byte[] data = new byte[DATA_SIZE];
byte[] result;
 
SHA1 sha = new SHA1CryptoServiceProvider();
// This is one implementation of the abstract class SHA1.
result = sha.ComputeHash(data);

http://msdn.microsoft.com/ko-kr/library/system.windows.forms.datagridview.virtualmode.aspx

가상 모드는 매우 큰 데이터 저장소와 함께 사용할 수 있도록 디자인되었습니다. VirtualMode 속성이 true로 설정되면 지정된 수의 행 및 열을 가진 DataGridView를 만든 후 CellValueNeeded 이벤트를 처리하여 셀을 채울 수 있습니다. 가상 모드를 사용하려면 사용자의 동작을 기준으로 DataGridView 셀의 채우기, 편집 및 삭제를 처리하기 위한 내부 데이터 캐시를 구현해야 합니다. 가상 모드 구현에 대한 자세한 내용은 방법: Windows Forms DataGridView 컨트롤에서 가상 모드 구현을 참조하십시오.

DataGridView 컨트롤이 바인딩된 모드에 있는 경우 바인딩되지 않은 열의 값을 유지하려면 가상 모드를 사용해야 합니다. 바인딩된 모드에서는 바인딩되지 않은 열을 기준으로 정렬할 수 없습니다.

대용량 모드에서 스크롤시 데이터를 불러와서 DataGridView 컨트롤에 바인딩 해 줄 수 있습니다.

using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System;

public class VirtualModeDemo : Form
{
    DataGridView dataGridView1 = new DataGridView();

    public VirtualModeDemo()
        : base()
    {
        Text = "DataGridView virtual-mode demo (cell-level commit scope)";
        dataGridView1.NewRowNeeded +=
            new DataGridViewRowEventHandler(dataGridView1_NewRowNeeded);
        dataGridView1.RowsAdded +=
            new DataGridViewRowsAddedEventHandler(dataGridView1_RowsAdded);
        dataGridView1.CellValidating +=
            new DataGridViewCellValidatingEventHandler(dataGridView1_CellValidating);
        dataGridView1.CellValueNeeded +=
            new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
        dataGridView1.CellValuePushed +=
            new DataGridViewCellValueEventHandler(dataGridView1_CellValuePushed);

        Controls.Add(dataGridView1);
        dataGridView1.VirtualMode = true;
        dataGridView1.AllowUserToDeleteRows = false;
        dataGridView1.Columns.Add("Numbers", "Positive Numbers");
        dataGridView1.Rows.AddCopies(0, initialSize);
    }

    bool newRowNeeded;
    private void dataGridView1_NewRowNeeded(object sender,
        DataGridViewRowEventArgs e)
    {
        newRowNeeded = true;
    }

    const int initialSize = 5000000;
    int numberOfRows = initialSize;

    private void dataGridView1_RowsAdded(object sender,
         DataGridViewRowsAddedEventArgs e)
    {
        if (newRowNeeded)
        {
            newRowNeeded = false;
            numberOfRows = numberOfRows + 1;
        }
    }

    #region "data store maintance"
    const int initialValue = -1;

    private void dataGridView1_CellValueNeeded(object sender,
        DataGridViewCellValueEventArgs e)
    {
        if (store.ContainsKey(e.RowIndex))
        {
            // Use the store if the e value has been modified
            // and stored.           
            e.Value = store[e.RowIndex];
        }
        else if (newRowNeeded && e.RowIndex == numberOfRows)
        {
            if (dataGridView1.IsCurrentCellInEditMode)
            {
                e.Value = initialValue;
            }
            else
            {
                // Show a blank value if the cursor is just resting
                // on the last row.
                e.Value = String.Empty;
            }
        }
        else
        {
            e.Value = e.RowIndex;
        }
    }

    private void dataGridView1_CellValuePushed(object sender,
        DataGridViewCellValueEventArgs e)
    {
        store.Add(e.RowIndex, int.Parse(e.Value.ToString()));
    }
    #endregion

    private Dictionary<int, int> store = new Dictionary<int, int>();

    private void dataGridView1_CellValidating(object sender,
        DataGridViewCellValidatingEventArgs e)
    {
        dataGridView1.Rows[e.RowIndex].ErrorText = "";
        int newInteger;

        // Don't try to validate the 'new row' until finished
        // editing since there
        // is not any point in validating its initial value.
        if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; }
        if (!int.TryParse(e.FormattedValue.ToString(),
            out newInteger) || newInteger < 0)
        {
            e.Cancel = true;
            dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer";
        }
    }

    [STAThreadAttribute()]
    public static void Main()
    {
        Application.Run(new VirtualModeDemo());
    }
}

http://msdn.microsoft.com/ko-kr/library/2b177d6d(VS.80).aspx

다음 코드 예제에서는 해당 VirtualMode 속성이 true로 설정된 DataGridView 컨트롤을 사용하여 큰 데이터 집합을 관리하는 방법을 보여 줍니다.

이 코드 예제에 대한 자세한 설명을 보려면 연습: Windows Forms DataGridView 컨트롤에서 가상 모드 구현을 참조하십시오.

 

using System;
using System.Windows.Forms;

public class Form1 : Form
{
    private DataGridView dataGridView1 = new DataGridView();

    // Declare an ArrayList to serve as the data store.
    private System.Collections.ArrayList customers =
        new System.Collections.ArrayList();

    // Declare a Customer object to store data for a row being edited.
    private Customer customerInEdit;

    // Declare a variable to store the index of a row being edited.
    // A value of -1 indicates that there is no row currently in edit.
    private int rowInEdit = -1;

    // Declare a variable to indicate the commit scope.
    // Set this value to false to use cell-level commit scope.
    private bool rowScopeCommit = true;

    [STAThreadAttribute()]
    public static void Main()
    {
        Application.Run(new Form1());
    }

    public Form1()
    {
        // Initialize the form.
        this.dataGridView1.Dock = DockStyle.Fill;
        this.Controls.Add(this.dataGridView1);
        this.Load += new EventHandler(Form1_Load);
        this.Text = "DataGridView virtual-mode demo (row-level commit scope)";
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Enable virtual mode.
        this.dataGridView1.VirtualMode = true;

        // Connect the virtual-mode events to event handlers.
        this.dataGridView1.CellValueNeeded += new
            DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
        this.dataGridView1.CellValuePushed += new
            DataGridViewCellValueEventHandler(dataGridView1_CellValuePushed);
        this.dataGridView1.NewRowNeeded += new
            DataGridViewRowEventHandler(dataGridView1_NewRowNeeded);
        this.dataGridView1.RowValidated += new
            DataGridViewCellEventHandler(dataGridView1_RowValidated);
        this.dataGridView1.RowDirtyStateNeeded += new
            QuestionEventHandler(dataGridView1_RowDirtyStateNeeded);
        this.dataGridView1.CancelRowEdit += new
            QuestionEventHandler(dataGridView1_CancelRowEdit);
        this.dataGridView1.UserDeletingRow += new
            DataGridViewRowCancelEventHandler(dataGridView1_UserDeletingRow);

        // Add columns to the DataGridView.
        DataGridViewTextBoxColumn companyNameColumn = new
            DataGridViewTextBoxColumn();
        companyNameColumn.HeaderText = "Company Name";
        companyNameColumn.Name = "Company Name";
        DataGridViewTextBoxColumn contactNameColumn = new
            DataGridViewTextBoxColumn();
        contactNameColumn.HeaderText = "Contact Name";
        contactNameColumn.Name = "Contact Name";
        this.dataGridView1.Columns.Add(companyNameColumn);
        this.dataGridView1.Columns.Add(contactNameColumn);
        this.dataGridView1.AutoSizeColumnsMode =
            DataGridViewAutoSizeColumnsMode.AllCells;

        // Add some sample entries to the data store.
        this.customers.Add(new Customer(
            "Bon app'", "Laurence Lebihan"));
        this.customers.Add(new Customer(
            "Bottom-Dollar Markets", "Elizabeth Lincoln"));
        this.customers.Add(new Customer(
            "B's Beverages", "Victoria Ashworth"));

        // Set the row count, including the row for new records.
        this.dataGridView1.RowCount = 4;
    }

    private void dataGridView1_CellValueNeeded(object sender,
        System.Windows.Forms.DataGridViewCellValueEventArgs e)
    {
        // If this is the row for new records, no values are needed.
        if (e.RowIndex == this.dataGridView1.RowCount - 1) return;

        Customer customerTmp = null;

        // Store a reference to the Customer object for the row being painted.
        if (e.RowIndex == rowInEdit)
        {
            customerTmp = this.customerInEdit;
        }
        else
        {
            customerTmp = (Customer)this.customers[e.RowIndex];
        }

        // Set the cell value to paint using the Customer object retrieved.
        switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
        {
            case "Company Name":
                e.Value = customerTmp.CompanyName;
                break;

            case "Contact Name":
                e.Value = customerTmp.ContactName;
                break;
        }
    }

    private void dataGridView1_CellValuePushed(object sender,
        System.Windows.Forms.DataGridViewCellValueEventArgs e)
    {
        Customer customerTmp = null;

        // Store a reference to the Customer object for the row being edited.
        if (e.RowIndex < this.customers.Count)
        {
            // If the user is editing a new row, create a new Customer object.
            if (this.customerInEdit == null)
            {
                this.customerInEdit = new Customer(
                    ((Customer)this.customers[e.RowIndex]).CompanyName,
                    ((Customer)this.customers[e.RowIndex]).ContactName);
            }
            customerTmp = this.customerInEdit;
            this.rowInEdit = e.RowIndex;
        }
        else
        {
            customerTmp = this.customerInEdit;
        }

        // Set the appropriate Customer property to the cell value entered.
        String newValue = e.Value as String;
        switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
        {
            case "Company Name":
                customerTmp.CompanyName = newValue;
                break;

            case "Contact Name":
                customerTmp.ContactName = newValue;
                break;
        }
    }

    private void dataGridView1_NewRowNeeded(object sender,
        System.Windows.Forms.DataGridViewRowEventArgs e)
    {
        // Create a new Customer object when the user edits
        // the row for new records.
        this.customerInEdit = new Customer();
        this.rowInEdit = this.dataGridView1.Rows.Count - 1;
    }

    private void dataGridView1_RowValidated(object sender,
        System.Windows.Forms.DataGridViewCellEventArgs e)
    {
        // Save row changes if any were made and release the edited
        // Customer object if there is one.
        if (e.RowIndex >= this.customers.Count &&
            e.RowIndex != this.dataGridView1.Rows.Count - 1)
        {
            // Add the new Customer object to the data store.
            this.customers.Add(this.customerInEdit);
            this.customerInEdit = null;
            this.rowInEdit = -1;
        }
        else if (this.customerInEdit != null &&
            e.RowIndex < this.customers.Count)
        {
            // Save the modified Customer object in the data store.
            this.customers[e.RowIndex] = this.customerInEdit;
            this.customerInEdit = null;
            this.rowInEdit = -1;
        }
        else if (this.dataGridView1.ContainsFocus)
        {
            this.customerInEdit = null;
            this.rowInEdit = -1;
        }
    }

    private void dataGridView1_RowDirtyStateNeeded(object sender,
        System.Windows.Forms.QuestionEventArgs e)
    {
        if (!rowScopeCommit)
        {
            // In cell-level commit scope, indicate whether the value
            // of the current cell has been modified.
            e.Response = this.dataGridView1.IsCurrentCellDirty;
        }
    }

    private void dataGridView1_CancelRowEdit(object sender,
        System.Windows.Forms.QuestionEventArgs e)
    {
        if (this.rowInEdit == this.dataGridView1.Rows.Count - 2 &&
            this.rowInEdit == this.customers.Count)
        {
            // If the user has canceled the edit of a newly created row,
            // replace the corresponding Customer object with a new, empty one.
            this.customerInEdit = new Customer();
        }
        else
        {
            // If the user has canceled the edit of an existing row,
            // release the corresponding Customer object.
            this.customerInEdit = null;
            this.rowInEdit = -1;
        }
    }

    private void dataGridView1_UserDeletingRow(object sender,
        System.Windows.Forms.DataGridViewRowCancelEventArgs e)
    {
        if (e.Row.Index < this.customers.Count)
        {
            // If the user has deleted an existing row, remove the
            // corresponding Customer object from the data store.
            this.customers.RemoveAt(e.Row.Index);
        }

        if (e.Row.Index == this.rowInEdit)
        {
            // If the user has deleted a newly created row, release
            // the corresponding Customer object.
            this.rowInEdit = -1;
            this.customerInEdit = null;
        }
    }
}

public class Customer
{
    private String companyNameValue;
    private String contactNameValue;

    public Customer()
    {
        // Leave fields empty.
    }

    public Customer(String companyName, String contactName)
    {
        companyNameValue = companyName;
        contactNameValue = contactName;
    }

    public String CompanyName
    {
        get
        {
            return companyNameValue;
        }
        set
        {
            companyNameValue = value;
        }
    }

    public String ContactName
    {
        get
        {
            return contactNameValue;
        }
        set
        {
            contactNameValue = value;
        }
    }
}

http://msdn.microsoft.com/ko-kr/library/sz6zd40f.aspx

  • 제네릭 소개(C# 프로그래밍 가이드)

  • 제네릭의 장점(C# 프로그래밍 가이드)

  • 제네릭 형식 매개 변수(C# 프로그래밍 가이드)

  • 형식 매개 변수에 대한 제약 조건(C# 프로그래밍 가이드)

  • 제네릭 클래스(C# 프로그래밍 가이드)

  • 제네릭 인터페이스(C# 프로그래밍 가이드)

  • 제네릭 메서드(C# 프로그래밍 가이드)

  • 제네릭 대리자(C# 프로그래밍 가이드)

  • 제네릭 코드의 default 키워드(C# 프로그래밍 가이드)

  • C++ 템플릿과 C# 제네릭의 차이점(C# 프로그래밍 가이드)

  • 제네릭 및 리플렉션(C# 프로그래밍 가이드)

  • 런타임의 제네릭(C# 프로그래밍 가이드)

  • .NET Framework 클래스 라이브러리의 제네릭(C# 프로그래밍 가이드)

  • 제네릭 샘플(C#)

  • 제네릭 클래스(C# 프로그래밍 가이드)

    업데이트: 2007년 11월

    제네릭 클래스는 특정 데이터 형식에 고유하지 않은 작업을 캡슐화합니다. 제네릭 클래스는 연결된 목록, 해시 테이블, 스택, 큐, 트리 등의 컬렉션에 가장 일반적으로 사용됩니다. 컬렉션에서 항목을 추가하고 제거하는 등의 작업은 저장되는 데이터의 형식에 관계없이 기본적으로 동일한 방식으로 수행됩니다.

    컬렉션 클래스가 필요한 대부분의 시나리오에서는 .NET Framework 클래스 라이브러리에서 제공하는 컬렉션 클래스를 사용하는 것이 좋습니다. 이러한 클래스 사용에 대한 자세한 내용은 .NET Framework 클래스 라이브러리의 제네릭(C# 프로그래밍 가이드)을 참조하십시오.

    일반적으로 기존의 구체적인 클래스로 시작하여 일반성과 편의성의 균형이 맞을 때까지 형식을 하나씩 형식 매개 변수로 바꾸는 방법으로 제네릭 클래스를 만듭니다. 사용자 고유의 제네릭 클래스를 만들 때는 다음과 같은 사항을 고려해야 합니다.

    • 형식 매개 변수로 일반화할 형식.

      일반적으로는 매개 변수화할 수 있는 형식이 많을수록 코드의 융통성과 재사용 가능성이 향상됩니다. 그러나 코드를 지나치게 일반화하면 다른 개발자가 읽거나 이해하기가 어려워집니다.

    • 형식 매개 변수에 적용할 제약 조건(형식 매개 변수에 대한 제약 조건(C# 프로그래밍 가이드) 참조).

      필요한 형식을 처리할 수 있는 범위 내에서 최대한 많은 제약 조건을 적용하는 것이 좋습니다. 예를 들어 사용자 제네릭 클래스를 참조 형식으로만 사용하려는 경우에는 클래스 제약 조건을 적용합니다. 이렇게 하면 클래스를 값 형식으로 잘못 사용하는 것을 막을 수 있고, T에 as 연산자를 사용하여 null 값 여부를 확인할 수 있습니다.

    • 제네릭 동작을 기본 클래스와 서브클래스로 분할할지 여부.

      제네릭 클래스는 기본 클래스가 될 수 있으므로 제네릭이 아닌 클래스에 적용되는 디자인 고려 사항이 동일하게 적용됩니다. 자세한 내용은 이 항목의 뒷부분에서 설명하는 제네릭 기본 클래스에서 상속하는 데 대한 규칙을 참조하십시오.

    • 제네릭 인터페이스를 하나 이상 구현할지 여부

      예를 들어 제네릭 기반 컬렉션의 항목을 만드는 데 사용될 클래스를 디자인하는 경우 IComparable<(Of <(T>)>)(T는 사용자 클래스 형식)과 같은 인터페이스를 구현해야 할 수 있습니다.

    간단한 제네릭 클래스의 예제를 보려면 제네릭 소개(C# 프로그래밍 가이드)를 참조하십시오.

    형식 매개 변수와 제약 조건에 대한 규칙은 제네릭 클래스 동작에서 특히 상속과 멤버 액세스 가능성에 대해 몇 가지 영향을 줍니다. 계속하려면 몇 가지 용어를 이해하고 있어야 합니다. Node<T>, 제네릭 클래스의 경우 클라이언트 코드에서는 형식 인수를 지정하여 폐쇄형 생성 형식(Node<int>)을 만드는 방법으로 클래스를 참조하거나, 제네릭 기본 클래스를 지정하는 경우와 같이 형식 매개 변수를 지정하지 않고 개방형 생성 형식(Node<T>)을 만드는 방법으로 클래스를 참조할 수 있습니다. 제네릭 클래스는 구체적인 클래스, 폐쇄형 구성 클래스 또는 개방형 구성 기본 클래스에서 상속할 수 있습니다.

    C#

    코드 복사

    class BaseNode { }
    class BaseNodeGeneric<T> { }
    
    // concrete type
    class NodeConcrete<T> : BaseNode { }
    
    //closed constructed type
    class NodeClosed<T> : BaseNodeGeneric<int> { }
    
    //open constructed type 
    class NodeOpen<T> : BaseNodeGeneric<T> { }

    제네릭이 아닌 구체적인 클래스는 폐쇄형 생성 기본 클래스에서는 상속할 수 있지만 개방형 생성 클래스 또는 naked 형식 매개 변수에서는 상속할 수 없습니다. 이는 런타임에 클라이언트 코드에서 기본 클래스를 인스턴스화할 때 필요한 형식 인수를 제공할 수 없기 때문입니다.

    C#

    코드 복사

    //No error
    class Node1 : BaseNodeGeneric<int> { }
    
    //Generates an error
    //class Node2 : BaseNodeGeneric<T> {}
    
    //Generates an error
    //class Node3 : T {}

    개방형 생성 형식에서 상속하는 제네릭 클래스에서는 다음 코드와 같이 상속하는 클래스에서 공유하지 않는 모든 기본 클래스 형식 매개 변수에 대해 형식 인수를 제공해야 합니다.

    C#

    코드 복사

    class BaseNodeMultiple<T, U> { }
    
    //No error
    class Node4<T> : BaseNodeMultiple<T, int> { }
    
    //No error
    class Node5<T, U> : BaseNodeMultiple<T, U> { }
    
    //Generates an error
    //class Node6<T> : BaseNodeMultiple<T, U> {} 

    개방형 생성 형식에서 상속하는 제네릭 클래스에서는 기본 형식에 대한 제약 조건을 포함하거나 암시하는 제약 조건을 지정해야 합니다.

    C#

    코드 복사

    class NodeItem<T> where T : System.IComparable<T>, new() { }
    class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

    제네릭 형식은 다음과 같이 여러 형식 매개 변수 및 제약 조건을 사용할 수 있습니다.

    C#

    코드 복사

    class SuperKeyType<K, V, U>
        where U : System.IComparable<U>
        where V : new()
    { }

    개방형 생성 형식 및 폐쇄형 생성 형식은 메서드 매개 변수로 사용될 수 있습니다.

    C#

    코드 복사

    void Swap<T>(List<T> list1, List<T> list2)
    {
        //code to swap items
    }
    
    void Swap(List<int> list1, List<int> list2)
    {
        //code to swap items
    }

    제네릭 클래스에서 인터페이스를 구현하면 이 클래스의 모든 인스턴스를 해당 인터페이스에 캐스팅할 수 있습니다.

    제네릭 클래스는 비가변적입니다. 즉, 입력 매개 변수에서 List<BaseClass>를 지정하면 List<DerivedClass>를 제공하려고 할 때 컴파일 타임 오류가 발생합니다.

      참고 항목

    개념

    C# 프로그래밍 가이드

    참조

    제네릭(C# 프로그래밍 가이드)

    System.Collections.Generic

    형식 매개 변수에 대한 제약 조건(C# 프로그래밍 가이드)

    제네릭 클래스를 정의하는 경우 클래스를 인스턴스화할 때 클라이언트 코드에서 형식 인수에 사용할 수 있는 형식의 종류에 제약 조건을 적용할 수 있습니다. 클라이언트 코드가 제약 조건에서 허용하지 않는 형식을 사용하여 클래스를 인스턴스화하려고 하면 컴파일 타임 오류가 발생합니다. 이러한 제한을 제약 조건이라고 합니다. 제약 조건은 컨텍스트 키워드 where를 사용하여 지정합니다. 다음 표에서는 여섯 가지의 형식 제약 조건을 보여 줍니다.

    제약 조건

    설명

    where T: struct

    형식 인수가 값 형식이어야 합니다. Nullable를 제외한 임의의 값 형식을 지정할 수 있습니다. 자세한 내용은 Nullable 형식 사용(C# 프로그래밍 가이드)을 참조하십시오.

    where T : class

    형식 인수가 참조 형식이어야 합니다. 이는 모든 클래스, 인터페이스, 대리자 또는 배열 형식에도 적용됩니다.

    where T : new()

    형식 인수가 매개 변수 없는 공용 생성자여야 합니다. 다른 제약 조건과 함께 사용하는 경우 new() 제약 조건은 마지막에 지정해야 합니다.

    where T : <기본 클래스 이름>

    형식 인수가 지정된 기본 클래스이거나 지정된 기본 클래스에서 파생되어야 합니다.

    where T : <인터페이스 이름>

    형식 인수가 지정된 인터페이스이거나 지정된 인터페이스를 구현해야 합니다. 여러 인터페이스 제약 조건을 지정할 수 있습니다. 제한하는 인터페이스는 제네릭이 될 수도 있습니다.

    where T : U

    T에 대해 지정한 형식 인수가 U에 대해 지정한 인수이거나 이 인수에서 파생되어야 합니다. 이를 naked 형식 제약 조건이라고 합니다.

      제약 조건 사용 이유

    제네릭 목록의 항목을 검사하여 그 유효성 여부를 확인하거나 이 항목을 다른 항목과 비교하려는 경우, 컴파일러는 클라이언트 코드에서 지정할 수 있는 모든 형식 인수에 대해 호출해야 할 메서드나 연산자가 지원되는지 확인해야 합니다. 하나 이상의 제약 조건을 제네릭 클래스 정의에 적용하면 이러한 확인이 가능합니다. 예를 들어, 기본 클래스 제약 조건에서는 이 형식의 개체와 이 형식에서 파생된 개체만이 형식 인수로 사용될 수 있음을 컴파일러에 알립니다. 컴파일러에서 이를 확인하면 사용자는 제네릭 클래스에서 해당 형식의 메서드를 호출할 수 있습니다. 제약 조건은 컨텍스트 키워드 where를 사용하여 적용됩니다. 다음 코드 예제에서는 기본 클래스 제약 조건을 적용하여 제네릭 소개(C# 프로그래밍 가이드)의 GenericList<T> 클래스에 추가할 수 있는 기능을 보여 줍니다.

    C#

    코드 복사

    public class Employee
    {
        private string name;
        private int id;
    
        public Employee(string s, int i)
        {
            name = s;
            id = i;
        }
    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        public int ID
        {
            get { return id; }
            set { id = value; }
        }
    }
    
    public class GenericList<T> where T : Employee
    {
        private class Node
        {
            private Node next;
            private T data;
    
            public Node(T t)
            {
                next = null;
                data = t;
            }
    
            public Node Next
            {
                get { return next; }
                set { next = value; }
            }
    
            public T Data
            {
                get { return data; }
                set { data = value; }
            }
        }
    
        private Node head;
    
        public GenericList() //constructor
        {
            head = null;
        }
    
        public void AddHead(T t)
        {
            Node n = new Node(t);
            n.Next = head;
            head = n;
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            Node current = head;
    
            while (current != null)
            {
                yield return current.Data;
                current = current.Next;
            }
        }
    
        public T FindFirstOccurrence(string s)
        {
            Node current = head;
            T t = null;
    
            while (current != null)
            {
                //The constraint enables access to the Name property.
                if (current.Data.Name == s)
                {
                    t = current.Data;
                    break;
                }
                else
                {
                    current = current.Next;
                }
            }
            return t;
        }
    }

    제약 조건을 사용하면 형식 T의 모든 항목이 항상 Employee 개체이거나 Employee에서 상속된 개체이므로 제네릭 클래스에서 Employee.Name 속성을 사용할 수 있습니다.

    여러 제약 조건을 동일한 형식 매개 변수에 적용할 수 있고 제약 조건 자체가 제네릭 형식일 수도 있습니다. 예를 들면 다음과 같습니다.

    C#

    코드 복사

    class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
    {
        // ...
    }

    형식 매개 변수를 제한하면, 허용되는 작업의 수 및 제한하는 형식과 해당 상속 계층 구조의 모든 형식에서 지원하는 메서드에 대해 허용되는 호출의 수를 늘릴 수 있습니다. 따라서 제네릭 클래스나 메서드를 디자인할 때 System.Object에서 지원하지 않는 메서드를 호출하거나 제네릭 멤버에 대해 단순한 할당 이상의 작업을 수행하려는 경우에는 형식 매개 변수에 제약 조건을 적용해야 합니다.

    where T : class 제약 조건을 적용할 때는 형식 매개 변수에 대해 == 및 != 연산자를 사용하지 않아야 합니다. 이러한 연산자에서는 값이 같은지 확인하는 대신 참조가 동일한지만 테스트하기 때문입니다. 인수로 사용되는 형식에서 이러한 연산자를 오버로드한 경우에도 마찬가지입니다. 다음 코드에서는 이러한 경우의 예를 보여 줍니다. String 클래스에서 == 연산자를 오버로드해도 false가 출력됩니다.

    C#

    코드 복사

    public static void OpTest<T>(T s, T t) where T : class
    {
        System.Console.WriteLine(s == t);
    }
    static void Main()
    {
        string s1 = "foo";
        System.Text.StringBuilder sb = new System.Text.StringBuilder("foo");
        string s2 = sb.ToString();
        OpTest<string>(s1, s2);
    }

    이러한 방식으로 동작하는 이유는 컴파일 시 컴파일러에는 T가 참조 형식이라는 정보만 제공되므로 모든 참조 형식에 유효한 기본 연산자가 사용되기 때문입니다. 값이 동일한지 테스트하려면 where T : IComparable<T> 제약 조건을 함께 적용하고 제네릭 클래스를 생성하는 데 사용되는 모든 클래스에서 해당 인터페이스를 구현하는 것이 좋습니다.

      여러 매개 변수 제한

    다음 예제와 같이 여러 매개 변수에 제약 조건을 적용하고 단일 매개 변수에 여러 제약 조건을 적용할 수 있습니다.

    C#

    코드 복사

    class Base { }
    class Test<T, U>
        where U : struct
        where T : Base, new() { }

      바인딩되지 않은 형식 매개 변수

    공용 클래스 SampleClass<T>{}의 T와 같이 제약 조건이 없는 형식 매개 변수를 바인딩되지 않은 형식 매개 변수라고 합니다. 바인딩되지 않은 형식 매개 변수에는 다음과 같은 규칙이 적용됩니다.

    • != 및 == 연산자를 사용할 수 없습니다. 구체적인 형식 인수에서 이러한 연산자를 지원하리라는 보장이 없기 때문입니다.

    • 바인딩되지 않은 형식 매개 변수와 System.Object 사이에 변환하거나 이 매개 변수를 임의의 인터페이스 형식으로 명시적으로 변환할 수 있습니다.

    • 바인딩되지 않은 형식 매개 변수를 null과 비교할 수 있습니다. 바인딩되지 않은 매개 변수를 null과 비교하는 경우 형식 인수가 값 형식이면 비교 결과로 항상 false가 반환됩니다.

      naked 형식 제약 조건

    제네릭 형식 매개 변수를 제약 조건으로 사용하는 경우 이를 naked 형식 제약 조건이라고 합니다. naked 형식 제약 조건은 다음 예제에서와 같이 자체 형식 매개 변수가 있는 멤버 함수에서 해당 매개 변수를 포함 형식의 형식 매개 변수로 제한해야 하는 경우에 유용합니다.

    C#

    코드 복사

    class List<T>
    {
        void Add<U>(List<U> items) where U : T {/*...*/}
    }

    위 예제에서 T는 Add 메서드의 컨텍스트에서는 naked 형식 제약 조건이고 List 클래스의 컨텍스트에서는 바인딩되지 않은 형식 매개 변수입니다.

    naked 형식 제약 조건은 제네릭 클래스 정의에도 사용할 수 있습니다. naked 형식 제약 조건도 다른 모든 형식 매개 변수와 마찬가지로 꺾쇠괄호 안에 선언해야 합니다.

    C#

    코드 복사

    //naked type constraint
    public class SampleClass<T, U, V> where T : V { }

    컴파일러에서는 naked 형식 제약 조건이 System.Object에서 파생된다는 점을 제외하고는 이 제약 조건에 대해 어떠한 정보도 알 수 없으므로 naked 형식 제약 조건과 제네릭 클래스를 함께 사용할 필요는 거의 없습니다. 제네릭 클래스에 대해 naked 형식 제약 조건을 사용하는 경우로는 두 형식 매개 변수 사이에 반드시 상속 관계가 있도록 정의하는 경우를 들 수 있습니다.

    web.Config

    ----------------------------------------------------------------------------------------------

    connecitonStrings 에서 사용하기

    ----------------------------------------------------------------------------------------------

    <connectionStrings>
      <add name="DBConnectionString" connectionString="연결정보"    providerName="System.Data.SqlClient" />
    </connectionStrings>

    소스(Class)코드

    using System.Configuration;

            public string DBconnString
            {
                get
                {
                    return ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString
                        ;
                }
            }

    ----------------------------------------------------------------------------------------------

    appSettings세팅에서 사용하기

    ----------------------------------------------------------------------------------------------

    web.config의 내용

    <configuration>

        <system.web>

            <customErrors mode="Off"/>

        </system.web>

        <appSettings>

            <add key="DSN" value="server=localhost; database=pubs; uid=sa; pwd=;"/>

        </appSettings>

    </configuration>

    소스(Class)코드

    위의 코드 내부에  String dsn = ConfigurationSettings.AppSettings["DSN"]; 를 삽입하시면 아무런 문제가 없을 껍니다.

    using System.Configuration;

    String dsn = ConfigurationSettings.AppSettings["DSN"];

    SqlConnection MyConnection = new SqlConnection(dsn);

    ----------------------------------------------------------------------------------------------

    *구성 검색

    ASP.NET을 통해 개발자는 구성 설정을 바로 강력한 형식의 속성으로 노출시키거나 일반 구성 API를 사용하여 응용 프로그램 내에서 구성 설정에 액세스할 수 있습니다. 다음 샘플은 System.Web.HttpRequest 클래스의 Browser 속성을 사용하여 <browserCaps> 구성 섹션에 액세스하는 페이지를 보여 줍니다. 이 샘플에 사용되는 데이터는 페이지에 현재 액세스하고 있는 브라우저 클라이언트의 기능을 반영하는 특성의 해시 테이블입니다. 실제 <browserCaps> 섹션 데이터는 machine.config 파일에 포함되어 있습니다.

    C# BrowsCaps.aspx

    [샘플 실행] | [소스 보기]

    위에 나와 있는 것처럼 개발자는 구성 설정에 액세스할 수 있을 뿐만 아니라 System.Configuration.ConfigurationSettings 클래스를 사용하여 임의 구성 섹션에 대한 데이터를 검색할 수 있습니다. ConfigurationSettings에서 반환하는 특정 개체는 구성 섹션에 매핑된 섹션 처리기에 따라 다릅니다(IConfigurationSectionHandler.Create 참조). 다음 코드는 <customconfig> 섹션에 대해 노출된 구성 데이터에 액세스할 수 있는 방법을 보여 줍니다. 이 샘플에서는 구성 섹션 처리기가 속성이 EnabledCustomConfigSettings 형식의 개체를 반환한다고 가정합니다.

    % style % -->

    CustomConfigSettings config = (CustomConfigSettings) ConfigurationSettings["customconfig"];
    if (config.Enabled == true) {
        // Do something here.
    }

    응용 프로그램 설정 사용

    구성 파일은 데이터베이스 연결 문자열, 파일 경로 또는 원격 XML 웹 서비스 URL 같은 사용자가 지정한 응용 프로그램 설정을 저장하는 데 적합합니다. machine.config 파일에 정의된 기본 구성 섹션에는 이러한 설정을 이름/값 쌍으로 저장하는 데 사용할 수 있는 <appSettings> 섹션이 포함되어 있습니다. 다음 샘플은 응용 프로그램의 데이터베이스 연결 문자열을 정의하는 <appSettings> 구성 섹션을 보여 줍니다.

    <configuration>

    <appSettings>

    <add key="pubs" value="server=(local)\NetSDK;database=pubs;Trusted_Connection=yes" />

    <add key="northwind" value="server=(local)\NetSDK;database=northwind;Trusted_Connection=yes" />

    </appSettings>

    </configuration>

    ConfigurationSettings 개체는 다음 설정을 검색하는 데 사용할 수 있는 특수한 AppSettings 속성을 노출시킵니다.

    String dsn = ConfigurationSettings.AppSettings["pubs"];

    다음 샘플에서는 이 기술에 대해 설명합니다.

    C# Config1.aspx

    [샘플 실행] | [소스 보기

    자식 요소

    요소
    설명

    anonymousIdentification 요소(ASP.NET 설정 스키마)

    응용 프로그램 권한 부여에 대해 익명 ID를 구성합니다. 이 ID는 권한 부여가 필요한 경우 인증되지 않은 엔터티를 식별하는 데 사용됩니다.

    authentication 요소(ASP.NET 설정 스키마)

    ASP.NET 인증 지원을 구성합니다.

    authorization 요소(ASP.NET 설정 스키마)

    ASP.NET 권한 부여 지원을 구성합니다.

    browserCaps 요소(ASP.NET 설정 스키마)

    브라우저 기능 구성 요소의 설정을 구성합니다.

    caching 요소(ASP.NET 설정 스키마)

    웹 응용 프로그램에 대한 캐시 설정을 구성합니다.

    clientTarget 요소(ASP.NET 설정 스키마)

    사용자 에이전트 별칭의 내부 컬렉션에 특정 사용자 에이전트의 별칭을 추가합니다.

    compilation 요소(ASP.NET 설정 스키마)

    ASP.NET에서 사용하는 모든 컴파일 설정을 포함합니다.

    customErrors 요소(ASP.NET 설정 스키마)

    ASP.NET 응용 프로그램에 대한 사용자 지정 오류 메시지를 정의합니다.

    deployment 요소(ASP.NET 설정 스키마)

    웹 응용 프로그램의 배포를 지원하는 데 사용되는 구성 설정을 정의합니다.

    deviceFilters 요소(ASP.NET 설정 스키마)

    사용자 에이전트나 브라우저에 따라 ASP.NET MobileCapabilities 클래스의 장치 또는 장치 클래스를 지정합니다. 페이지 또는 응용 프로그램 개발자는 레이아웃과 모양을 변경할 템플릿 또는 콘텐츠 블록을 정의하거나 컨트롤 속성을 재정의하기 위해 장치 필터를 사용할 수 있습니다.

    globalization 요소(ASP.NET 설정 스키마)

    응용 프로그램의 전역화 설정을 구성합니다.

    <healthMonitoring> Element

    상태 모니터링에 대한 응용 프로그램을 구성합니다.

    hostingEnvironment 요소(ASP.NET 설정 스키마)

    응용 프로그램 호스팅 환경의 동작을 제어하는 구성 설정을 정의합니다.

    httpCookies 요소(ASP.NET 설정 스키마)

    웹 응용 프로그램에 사용되는 쿠키의 속성을 구성합니다.

    httpHandlers 요소(ASP.NET 설정 스키마)

    들어오는 URL 요청을 IHttpHandler 클래스에 매핑합니다.

    httpModules 요소(ASP.NET 설정 스키마)

    응용 프로그램 내에서 HTTP 모듈을 추가하거나 제거하거나 지웁니다.

    httpRuntime 요소(ASP.NET 설정 스키마)

    ASP.NET HTTP 런타임 설정을 구성합니다.

    이 섹션은 시스템, 사이트, 응용 프로그램 또는 하위 디렉터리 수준에서 선언할 수 있습니다.

    identity 요소(ASP.NET 설정 스키마)

    웹 응용 프로그램의 응용 프로그램 ID를 제어합니다.

    machineKey 요소(ASP.NET 설정 스키마)

    폼 인증 쿠키 데이터를 암호화하고 해독하는 데 사용할 키를 구성합니다.

    이 섹션을 사용하면 뷰 상태 데이터 및 폼 인증 티켓에 대해 메시지 인증 검사를 수행하는 유효성 검사 키를 구성할 수 있습니다.

    이 섹션은 컴퓨터, 사이트 또는 응용 프로그램 수준에서 선언할 수 있지만 하위 디렉터리 수준에서는 선언할 수 없습니다.

    membership 요소(ASP.NET 설정 스키마)

    ASP.NET 멤버 자격에 대해 사용자 계정을 관리하고 인증하기 위한 매개 변수를 구성합니다.

    mobileControls 요소(ASP.NET 설정 스키마)

    ASP.NET 모바일 컨트롤을 Web.config 파일의 system.web 섹션에 있는 해당 어댑터에 매핑하는 어댑터 집합을 정의합니다.

    pages 요소(ASP.NET 설정 스키마)

    페이지별 구성 설정을 식별합니다.

    processModel 요소(ASP.NET 설정 스키마)

    IIS(인터넷 정보 서비스) 웹 서버 시스템에서 ASP.NET 프로세스 모델 설정을 구성합니다.

    profile 요소(ASP.NET 설정 스키마)

    ASP.NET 프로필을 사용하여 사용자 값을 관리하기 위한 매개 변수를 구성합니다.

    roleManager 요소(ASP.NET 설정 스키마)

    역할 관리에 대한 응용 프로그램을 구성합니다.

    이 요소는 .NET Framework 버전 2.0에서 새로 도입되었습니다.

    securityPolicy 요소(ASP.NET 설정 스키마)

    정책 파일에 명명된 보안 수준을 적절히 매핑하도록 정의합니다.

    이 섹션은 시스템, 사이트 또는 응용 프로그램 수준에서 선언할 수 있습니다.

    sessionPageState 요소(ASP.NET 설정 스키마)

    ASP.NET 응용 프로그램의 페이지 뷰 상태 설정을 구성합니다.

    sessionState 요소(ASP.NET 설정 스키마)

    세션 상태 모듈을 구성합니다.

    siteMap 요소(ASP.NET 설정 스키마)

    사이트 탐색을 구성, 저장 및 렌더링하기 위해 탐색 인프라를 지원하도록 구성합니다.

    trace 요소(ASP.NET 설정 스키마)

    ASP.NET 추적 서비스를 구성합니다.

    trust 요소(ASP.NET 설정 스키마)

    특정 응용 프로그램을 실행하는 데 사용되는 코드 액세스 보안 권한 집합을 구성합니다.

    이 섹션은 시스템, 사이트 및 응용 프로그램 수준에서 선언할 수 있습니다.

    urlMappings 요소(ASP.NET 설정 스키마)

    실제 URL을 숨기고 사용자에게 친숙한 URL로 연결하는 매핑을 정의합니다.

    webControls 요소(ASP.NET 설정 스키마)

    클라이언트 스크립트 파일의 공유 위치를 지정합니다.

    webParts

    웹 파트 개인 설정 공급자를 지정하고, 개인 설정 권한을 설정하고, 웹 파트 연결에 사용할 WebPartTransformer 클래스를 확장하는 사용자 지정 클래스를 추가합니다.

    webServices 요소(ASP.NET 설정 스키마)

    ASP.NET을 사용하여 만든 XML Web services의 설정을 제어합니다.

    xhtmlConformance 요소(ASP.NET 설정 스키마)

    XHTML 1.0에 맞는 컨트롤 렌더링을 구성합니다.

    http://msdn.microsoft.com/en-us/library/ms733127.aspx

    using System.ServiceModel;
    using System.ServiceModel.Description;

    namespace IChannel
    {
        [ServiceContract]
        public  interface IHelloWorld
        {
            [OperationContract]
            string Hellworld();
        }
    }

    저번에 메소드를 서비스하기 위해서 명시적으로 표시했습니다.

    그서비스를 통해서 데이터를 주고받기 위해서 클래스를 하나 생성합니다 그리곤 아래와 같이 명시적으로 표시합니다.[DataContract],[DataMember]

    using System;
    using System.Runtime.Serialization;

    namespace MyTypes
    {
        [DataContract]
        public class PurchaseOrder
        {
            private int poId_value;

            // Apply the DataMemberAttribute to the property.
            [DataMember]
            public int PurchaseOrderId
            {

                get { return poId_value; }
                set { poId_value = value; }
            }
        }
    }

    방법: 엔터티 형식을 반환하는 쿼리 실행

    LINQ Entity

    using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
    {
        ObjectQuery<Product> products = AWEntities.Product;
        IQueryable<Product> productsQuery = from product in products
                                            select product;

        Console.WriteLine("Product Names:");
        foreach (var prod in productsQuery)
        {
            Console.WriteLine(prod.Name);
        }
    }

    Entity SQL

    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        // Specify the order amount.
        decimal orderCost = 2500;

        // Specify the Entity SQL query that returns only online orders
        // more than the specified amount.
        string queryString = @"SELECT VALUE o FROM SalesOrderHeader AS o
            WHERE o.OnlineOrderFlag = TRUE AND o.TotalDue > @ordercost";

        try
        {
            // Define an ObjectQuery and pass the maxOrderCost parameter.
            ObjectQuery<SalesOrderHeader> onlineOrders =
                new ObjectQuery<SalesOrderHeader>(queryString, context);
            onlineOrders.Parameters.Add(
                new ObjectParameter("ordercost", orderCost));

            // Print order information.
            foreach (var onlineOrder in onlineOrders)
            {
                Console.WriteLine("Order ID: {0} Order date: "
                    + "{1:d} Order number: {2}",
                    onlineOrder.SalesOrderID,
                    onlineOrder.OrderDate,
                    onlineOrder.SalesOrderNumber);
            }
        }
        catch (EntitySqlException ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    집계 데이터

    LINQ to Entities

    using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
    {
        ObjectQuery<SalesOrderHeader> orders = AWEntities.SalesOrderHeader;

        var query =
            from order in orders
            group order by order.Contact.ContactID into g
            select new
            {
                Category = g.Key,
                averageTotalDue = g.Average(order => order.TotalDue)
            };

        foreach (var order in query)
        {
            Console.WriteLine("ContactID = {0} \t Average TotalDue = {1}",
                order.Category, order.averageTotalDue);
        }
    }

     

    Entity SQL

    using (AdventureWorksEntities advWorksContext =
        new AdventureWorksEntities())
    {
        string esqlQuery = @"SELECT contactID, AVG(order.TotalDue)
                                FROM AdventureWorksEntities.SalesOrderHeader
                                AS order GROUP BY order.Contact.ContactID as contactID";

        try
        {
            foreach (DbDataRecord rec in
                new ObjectQuery<DbDataRecord>(esqlQuery, advWorksContext))
            {
                Console.WriteLine("ContactID = {0}  Average TotalDue = {1} ",
                    rec[0], rec[1]);
            }
        }
        catch (EntityException ex)
        {
            Console.WriteLine(ex.ToString());
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    + Recent posts