PDA

View Full Version : سوال: چگونگي محدود كردن دسترسي به كامپوننتهاي بكار رفته در يك dll



رافعی مهدی
جمعه 05 مهر 1387, 12:01 عصر
سلام
يه پروژه از نوع Class Library دارم و در اون دو تا User Control گذاشتم. (UC1 و UC2) نحوه ي طراحي UC2 بشكلي است كه از UC1 بعنوان كلاس پايه ارث بري ميكنه. وقتي dll (دات نت اسمبلي) اين پروژه ساخته ميشه و به يه پروژه ديگه اضافه ميشه هر دوتاي اين User Control ها شناخته ميشوند و قابل دسترسي هستند.
هدف از ايجاد اين dll فقط ايجاد UC2 بوده و UC1 فقط به طراحي UC2 كمك ميكنه. سوال اينه كه چطوري ميتونم كاري كنم كه وقتي از اين dll در يه پروژه ي ديگه استفاده ميكنم تنها UC2 شناخته بشه و قابل دسترسي باشه؟


موارد امتحان شده:
تغيير سطح دسترسي UC1 از حالت public به internal. نتيجه: مواجهه با خطاي Inconsistent Accessibility. (كلاس پايه ،UC1، سطح دسترسي پايينتري نسبت به اين كلاس ،UC2، دارد)
قرار دادن UC1 در يه پروژه ي ديگه از نوع Class Library در همون Solution و توليد dll مجزايي براي آن و بكارگيري اين dll جهت ساخت dll اي براي UC2. نتيجه: اگر بخواهيم از UC2.dll استفاده كنيم حتماً بايد UC1.dll هم reference داده بشه. بنابراين باز هم به UC1 دسترسي وجود خواهد داشت.

.

رضا عربلو
جمعه 05 مهر 1387, 13:28 عصر
همون internal مشکل شما را حل می کند. احتمالاً کدتان جای دیگری مشکل دارد. دو تا کلاس را بدون بدنه پیاده سازی کنید خواهید دید.
برای مثال در کلاس UC2 یک متد دارید که Public است و یک نوع از UC1 بر می گرداند که از آنجا که UC1 بصورت internal تعریف شده است در خارج از اسمبلی نمی توان به آن دسترسی داشت و با خطای Inconsistent Accessibility. مواجه خواهید شد. برای رفع این مشکل می توانید از Interface استفاده کنید.

رافعی مهدی
جمعه 05 مهر 1387, 22:36 عصر
برای مثال در کلاس UC2 یک متد دارید که Public است و یک نوع از UC1 بر می گرداند
؟ ؟ ؟ توجه كنيد كه UC2 از UC1 ارث بري ميكند. اگر UC1 اينترنال باشه داريم:


internal class UC1 : UserControl


و


public class UC2 : UC1


كه در اينصورت خطاي گفته شده اتفاق مي افته. راستش من متوجه راهنمايي شما در مورد استفاده از internal يا كمك گرفتن از interface نشدم. لطفاً بيشتر توضيح بديد.





رافعی مهدی
شنبه 06 مهر 1387, 03:56 صبح
مشكلم با استفاده از abstract كردن كلاس UC1 حل شد. چون من فقط ميخواستم از اين كلاس يه كلاس ديگر ( UC2 ) رو مشتق كنم، ولي از خودش instance نگيرم. :لبخندساده:



ولي براي حالتي كه بخواهيم از UC1 درون UC2 استفاده كنيم چي كار بايد كرد؟ مثلاً UC1 نوعي TextBox با خصوصيات منحصر بفرد باشه و از اون يه نمونه داخل UC2 قرار بديم و در انتهاي كار dll حاصله اجازه ي instance گرفتن از UC1 رو ندهد و فقط از UC2 بشه نمونه گرفت.




.

رضا عربلو
شنبه 06 مهر 1387, 15:52 عصر
هر دو تا تایپ ات را از نوع اینترنال تعریف کن و از InternalsVisibleToAttribute استفاده کن


[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]
internal class UC2 : UC1
{
}

رافعی مهدی
یک شنبه 07 مهر 1387, 08:34 صبح
مشکل در وضعیت اول حل شد...
حالا راجع به زمانی که بخواهيم از UC1 بعنوان یکی از کامپوننتهای داخلی UC2 استفاده كنيم چي كار بايد كرد؟



.

رضا عربلو
یک شنبه 07 مهر 1387, 15:24 عصر
منظورتان را درست متوجه نشدم. اگر منظورتان استفاده از Internal type ها است :


Class UC2
{
Class UC1
{
}
}


و اگر منظورت یک متد در داخل UC2 است که یک ایجیکت از نوع UC1 بر می گرداند و همچنام مشکل Inconsistent Accessibility را داردی. می توانی یک نوع object بر گردانی و مت مربوطه را با کمک کلاس System.Activator فرا بخوانی و یا از Interface استفاده کنی و یا ....

رافعی مهدی
یک شنبه 07 مهر 1387, 16:07 عصر
جناب عربلو:
منظورم اینه که ...
فرض کنید یک کامپوننت میسازیم مثل UC1 . بعد برای طراحی یه کامپوننت دیگه، یک یا چند تا از این کامپوننت UC1 رو Drag-Drop میکنیم روی کامپوننت جدیدمون مثل UC2. (یعنی UC2 خودش دربرگیرنده ی یک یا چند تا UC1 هست) حالا میخواهیم یه dll بسازیم که وقتی به یه پروژه add میشه حاصلش فقط کامپوننت UC2 باشه و کسی که از اون dll استفاده میکنه نتونه به کامپوننت UC1 دسترسی داشته باشه.
[خودم هیچ ایده ی پیش فرضی رو برای پیشنهاد ندارم]
لطفاً راه حلتون رو بصورت کامل شرح بدید. خیلی ممنون

رضا عربلو
یک شنبه 07 مهر 1387, 16:42 عصر
از UserControl استفاده کن.

رافعی مهدی
دوشنبه 08 مهر 1387, 00:22 صبح
از UserControl استفاده کن.
از اينكه اينقدر راه حلت رو به صورت كامل شرح دادي ممنونم. هر چند من كه نفهميدم منظورت چيه؟ مگه UserControl خودش يه جور كامپوننت نيست؟


.

رضا عربلو
دوشنبه 08 مهر 1387, 15:49 عصر
در Solution explorer بر روی پروژه ات رایت کلیک کن و گزینه New Item را انتخاب کن. اونجا User Control را انتخاب کن. در داخل آن می توانی هر تعدادی کامپاننت قرار دهی و می توانی آن را در دیگر فرم هایت استفاده کنی. تنها کافی است یکبار پروژه ات را کامپایل کنی خودش به ToolBox اضافه می شود.

رافعی مهدی
سه شنبه 09 مهر 1387, 10:30 صبح
در پست اول نوشتم:

يه پروژه از نوع Class Library دارم و در اون دو تا User Control گذاشتم. (UC1 و UC2)...
در پست 8# گفته بودم:

فرض کنید یک کامپوننت میسازیم مثل UC1
احتمالاً مقایسه ی نام UC1 ( مخفف UserControl1 ) در این پست با پست اول نشون میده که منظورم اینه که این کامپوننت جدید رو با استفاده از User Control میسازم. البته ممکنه بین استفاده از کلمه ی Control و Component با هم اختلاف داشته باشیم. (که خودش جای بحث داره) حالا توی پست دهم نوشتم:

مگه UserControl خودش يه جور كامپوننت نيست؟
و شما نحوه ی ایجاد یک UC رو توضیح دادی!!
اینکه در پست 8# نوشتم:

خودم هیچ ایده ی پیش فرضی رو برای پیشنهاد ندارم
در کنار پستهای قبلی به معنی اینه که: برای محدود کردن سطح دسترسی به UC1 برای کسی که از dll حاصله استفاده میکنه، ایده ای ندارم. چون مثلاً اگر UC1 ها رو internal تعریف کنیم، دیگه در یک کلاس public نمیشه از اونها instance گرفت.

اما واقعاً تعیین سطح دسترسی به کامپوننتهایی (کنترلهایی (بالاخص یوزرکنترلهایی)) که برای ایجاد یک کامپوننت (کنترل) نهایی در غالب یک dll بکار گرفته میشوند، به استفاده از کلاس Component یا UserControl بستگی داره؟!!


درخواست: درست کردن یک dll وقت زیادی نمیگیره. اگه امکان داره پروژه ای رو upload کنید که حاصلش UC2.dll باشه و برای طراحی این UC2 از یک یا چند تا UC1 استفاده شده باشه ولی وقتی از UC2.dll استفاده میکنیم به UC1 دسترسی نداشته باشیم. [میشه UC1 رو در حد امکان ساده طراحی کرد که در حد چند ثانیه بیشتر وقت نگیره]. (مثلاً فقط یه Label روش بگذارید)





رافعی مهدی
سه شنبه 09 مهر 1387, 15:37 عصر
در MSDN نوشته:




This example contains two files, Assembly1.cs and Assembly2.cs. The first file contains an internal base class, BaseClass. In the second file, an attempt to instantiate BaseClass will produce an error.


// Assembly1.cs
// Compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}

// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}


In this example, use the same files you used in example 1, and change the accessibility level of BaseClass to public. Also change the accessibility level of the member IntM to internal. In this case, you can instantiate the class, but you cannot access the internal member.


// Assembly2.cs
// Compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}

// Assembly2_a.cs
// Compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}

بر این اساس نباید بتوان از یک کلاس internal در یک کلاس instance , public گرفت و یا حتی از متغیرهای static که internal هم باشند استفاده کرد.
اما برای ایجاد پروژه ای که در پست قبل درخواست آن را دادم، استفاده از کلاس internal رو امتحان کردم و پروژه بدون هیچ ایرادی UC2.dll رو به همون شکلی که میخواستم ایجاد کرد. برای این کار کلاس UC1 رو به صورت internal و کلاس UC2 رو بشکل public تعریف کردم ولی error اتفاق نیفتاد و dll تنها با دسترسی به UC2 ساخته شد، درحالی که در متد ()InitializeComponent از UC1 داره instance گرفته میشه. چرا؟

jaza_sa
سه شنبه 09 مهر 1387, 17:25 عصر
سطح دسترسی رو protected تعریف کنید
منبع : http://msdn.microsoft.com/en-us/library/bcd5672a(VS.71).aspx

SMRAH1
چهارشنبه 10 مهر 1387, 03:13 صبح
سلام

اگر UC2 از UC1 ارث بری کنه و در یک اسمبلی باشند،

درحالی که در متد ()InitializeComponent از UC1 داره instance گرفته میشه
دیگه معنی نداره.در واقعه کلاس UC2 داخل اسمبلی این کار رو می کنه و اجازه این کار رو هم داره.

رافعی مهدی
چهارشنبه 10 مهر 1387, 14:43 عصر
سطح دسترسی رو protected تعریف کنید
منبع : http://msdn.microsoft.com/en-us/library/bcd5672a(VS.71).aspx
كلاس ها رو كه نميشه بصورت protected تعريف كرد. لطفاً پيشنهادتان رو واضح تر بفرماييد. [حتي المقدور با يك تكه كد كوچك و كلي]

خيلي ممنون