最近很多小伙伴都在问php–在Yii中,为什么要使用CActiveDataProvider而不是Post::model()–>findAll()?这两个问题,那么本篇文章就来给大家详细解答一下,同时本
最近很多小伙伴都在问php – 在Yii中,为什么要使用CActiveDataProvider而不是Post :: model() – > findAll()?这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展android – 在SyncAdapter中使用ContentResolver而不是ContentProviderClient、android.provider.ContactsContract.CommonDataKinds.StructuredPostal的实例源码、ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidatorProvider、asp.net-mvc – MVC 2 vs MVC 3自定义验证属性使用DataAnnotationsModelValidatorProvider.RegisterAdapter等相关知识,下面开始了哦!
本文目录一览:- php – 在Yii中,为什么要使用CActiveDataProvider而不是Post :: model() – > findAll()?
- android – 在SyncAdapter中使用ContentResolver而不是ContentProviderClient
- android.provider.ContactsContract.CommonDataKinds.StructuredPostal的实例源码
- ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidatorProvider
- asp.net-mvc – MVC 2 vs MVC 3自定义验证属性使用DataAnnotationsModelValidatorProvider.RegisterAdapter
php – 在Yii中,为什么要使用CActiveDataProvider而不是Post :: model() – > findAll()?
使用它而不仅仅是Post :: model() – > findAll()有什么区别吗?
解决方法
如果您只需要获取数据并以任何其他方式使用它,但没有CListView或CGridView提供的智能渲染机制 – 使用CActiveRecord,因为除了获取数据之外它不执行任何其他操作.
reference
android – 在SyncAdapter中使用ContentResolver而不是ContentProviderClient
但是,与此同时,它可以访问ContentResolver,它允许在其他ContentProviders上运行查询.如果需要开发人员为SyncAdapter提供单一内容权限,我无法理解这个特定的设计概念,尽管如此,她仍然能够在她有权访问的任何ContentProvider上做任何她想做的事情.我的问题是:忽略onPerformSync的参数有什么后果:字符串权限和ContentProviderClient提供程序以及纯ContentResolver?
我的应用程序(实际上是它的SyncService)的想法很简单:查询日历服务器(在我的情况下为OwnCloud)不仅可以获取事件(与com.android.calendar同步),还可以获取VTodoS,然后可以在各种任务管理应用程序之间分配,我可以获取源代码和/或ContentProviderContract.我还想到了我自己的“Hub”ContentProvider,它具有基本的VTodo / Task结构,并且是与服务器相比唯一的一个.它应该能够与任务管理应用程序的不同内容提供程序同步2路,然后它与服务器同步.
我读过using ContentProviderClient vs ContentResolver to access content provider,我想我明白了它的不同之处.我现在感到困惑的是为什么Android SDK中有如此强烈的建议在单个SyncAdapter中使用单个ContentProvider但你可以使用ContentResolver来绕过这个限制.
我花了一整天的时间来搞清楚这一点并在此问题上搜索了数百个SO / Google资源(其中一些是多次).我还看到了有关使用一个SyncAdapter来同步多个ContentProviders的问题,但没有一个答案与使用ContentResolver的建议相近.
解决方法
这个事实很容易在AbstractThreadedSyncAdapter.SyncThread的源代码中看到 – 传递给onPerformSync()的ContentProviderClient是以标准方式获得的:
@Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // Trace this sync instance. Note,conceptually this should be in // SyncStorageEngine.insertStartSyncEvent(),but the trace functions require unique // threads in order to track overlapping operations,so we'll do it here for Now. Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER,mAuthority); SyncResult syncResult = new SyncResult(); ContentProviderClient provider = null; try { if (isCanceled()) { return; } provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority); if (provider != null) { AbstractThreadedSyncAdapter.this.onPerformSync(mAccount,mExtras,mAuthority,provider,syncResult); } else { syncResult.databaseError = true; } } finally { Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER); if (provider != null) { provider.release(); } if (!isCanceled()) { mSyncContext.onFinished(syncResult); } // synchronize so that the assignment will be seen by other threads // that also synchronize accesses to mSyncThreads synchronized (mSyncThreadLock) { mSyncThreads.remove(mThreadsKey); } } }
因此,引导线:您可以根据需要在SyncAdapter中使用ContentResolver – 只需调用getContext().getContentResolver()并访问任何导出的ContentProvider.
android.provider.ContactsContract.CommonDataKinds.StructuredPostal的实例源码
/** * Add an address to a list of database actions to be performed * * @param ops the list of database actions * @param address the item to be inserted */ private void insertAddress(ArrayList<ContentProviderOperation> ops,JSONObject address) { ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,0) .withValue(ContactsContract.Data.MIMETYPE,CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) .withValue(CommonDataKinds.StructuredPostal.TYPE,getAddresstype(getJsonString(address,"type"))) .withValue(CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS,getJsonString(address,"formatted")) .withValue(CommonDataKinds.StructuredPostal.STREET,"streetAddress")) .withValue(CommonDataKinds.StructuredPostal.CITY,"locality")) .withValue(CommonDataKinds.StructuredPostal.REGION,"region")) .withValue(CommonDataKinds.StructuredPostal.POSTCODE,"postalCode")) .withValue(CommonDataKinds.StructuredPostal.COUNTRY,"country")) .withValue(CommonDataKinds.StructuredPostal.LABEL,"type")) .build()); }
/** * Converts a string from the W3C Contact API to it's Android int value. * @param string * @return Android int value */ private int getAddresstype(String string) { int type = CommonDataKinds.StructuredPostal.TYPE_OTHER; if (string != null) { String lowerType = string.toLowerCase(Locale.getDefault()); if ("work".equals(lowerType)) { return CommonDataKinds.StructuredPostal.TYPE_WORK; } else if ("other".equals(lowerType)) { return CommonDataKinds.StructuredPostal.TYPE_OTHER; } else if ("home".equals(lowerType)) { return CommonDataKinds.StructuredPostal.TYPE_HOME; } return CommonDataKinds.StructuredPostal.TYPE_CUSTOM; } return type; }
/** * getPhoneType converts an Android phone type into a string * @param type * @return phone type as string. */ private String getAddresstype(int type) { String stringType; switch (type) { case CommonDataKinds.StructuredPostal.TYPE_HOME: stringType = "home"; break; case CommonDataKinds.StructuredPostal.TYPE_WORK: stringType = "work"; break; case CommonDataKinds.StructuredPostal.TYPE_OTHER: default: stringType = "other"; break; } return stringType; }
private ContentValues createAddressContentValues(final JSONObject address,final int typeConstant,final String type) throws JSONException { ContentValues contentValues = new ContentValues(); contentValues.put(Data.MIMETYPE,StructuredPostal.CONTENT_ITEM_TYPE); contentValues.put(StructuredPostal.STREET,address.optString("streetAddress")); contentValues.put(StructuredPostal.CITY,address.optString("locality")); contentValues.put(StructuredPostal.REGION,address.optString("region")); contentValues.put(StructuredPostal.POSTCODE,address.optString("postalCode")); contentValues.put(StructuredPostal.COUNTRY,address.optString("countryName")); if (type != null) { contentValues.put(StructuredPostal.TYPE,typeConstant); // If a custom type,add a label if (typeConstant == BaseTypes.TYPE_CUSTOM) { contentValues.put(StructuredPostal.LABEL,type); } } if (address.has("pref")) { contentValues.put(Data.IS_SUPER_PRIMARY,address.getBoolean("pref") ? 1 : 0); } return contentValues; }
private void initColumnNameConstantsMap() { if (mColumnNameConstantsMap != null) { return; } mColumnNameConstantsMap = new HashMap<String,String>(); mColumnNameConstantsMap.put("name",Structuredname.disPLAY_NAME); mColumnNameConstantsMap.put("givenname",Structuredname.GIVEN_NAME); mColumnNameConstantsMap.put("familyname",Structuredname.FAMILY_NAME); mColumnNameConstantsMap.put("honorificprefix",Structuredname.PREFIX); mColumnNameConstantsMap.put("honorificsuffix",Structuredname.SUFFIX); mColumnNameConstantsMap.put("additionalname",CUSTOM_DATA_COLUMN); mColumnNameConstantsMap.put("nickname",Nickname.NAME); mColumnNameConstantsMap.put("adr",StructuredPostal.STREET); mColumnNameConstantsMap.put("email",Email.ADDRESS); mColumnNameConstantsMap.put("url",Website.URL); mColumnNameConstantsMap.put("category",GroupMembership.GROUP_ROW_ID); mColumnNameConstantsMap.put("tel",Phone.NUMBER); mColumnNameConstantsMap.put("org",Organization.COMPANY); mColumnNameConstantsMap.put("jobTitle",Organization.TITLE); mColumnNameConstantsMap.put("note",Note.NOTE); mColumnNameConstantsMap.put("impp",Im.DATA); mColumnNameConstantsMap.put("sex",CUSTOM_DATA_COLUMN); mColumnNameConstantsMap.put("genderidentity",CUSTOM_DATA_COLUMN); mColumnNameConstantsMap.put("key",CUSTOM_DATA_COLUMN); }
public ContactOperations updateAddress(String city,String country,String neighborhood,String poBox,String postcode,String region,String street,String label,boolean isPrimary,boolean isSuperPrimary,Uri uri) { mValues.clear(); mValues.put(StructuredPostal.CITY,city); mValues.put(StructuredPostal.COUNTRY,country); mValues.put(StructuredPostal.NEIGHBORHOOD,neighborhood); mValues.put(StructuredPostal.POBox,poBox); mValues.put(StructuredPostal.POSTCODE,postcode); mValues.put(StructuredPostal.REGION,region); mValues.put(StructuredPostal.STREET,street); mValues.put(StructuredPostal.LABEL,label); mValues.put(StructuredPostal.IS_PRIMARY,isPrimary ? 1 : 0); mValues.put(StructuredPostal.IS_SUPER_PRIMARY,isSuperPrimary ? 1 : 0); addUpdateOp(uri); return this; }
@Override public boolean addPostal(ContactStruct contact,Cursor postals,boolean removeMatches) { String address = postals.getString(postals .getColumnIndex(StructuredPostal.FORMATTED_ADDRESS)); String poBox = postals.getString(postals.getColumnIndex(StructuredPostal.POBox)); String street = postals.getString(postals.getColumnIndex(StructuredPostal.STREET)); String nbrhood = postals.getString(postals.getColumnIndex(StructuredPostal.NEIGHBORHOOD)); String city = postals.getString(postals.getColumnIndex(StructuredPostal.CITY)); String state = postals.getString(postals.getColumnIndex(StructuredPostal.REGION)); String postCode = postals.getString(postals.getColumnIndex(StructuredPostal.POSTCODE)); String country = postals.getString(postals.getColumnIndex(StructuredPostal.COUNTRY)); String label = postals.getString(postals.getColumnIndexOrThrow(StructuredPostal.LABEL)); int type = postals.getInt(postals.getColumnIndexOrThrow(StructuredPostal.TYPE)); boolean primary = (postals.getInt(postals .getColumnIndexOrThrow(StructuredPostal.IS_PRIMARY)) != 0); if (!TextUtils.isEmpty(address) && isPostalNew(contact,address,poBox,street,nbrhood,city,state,postCode,type,removeMatches)) { contact.addAddress(type,country,label,primary); return true; } return false; }
private ContentValues valuesPostal(Address postal) { ContentValues val = new ContentValues(); val.put(Data.MIMETYPE,StructuredPostal.CONTENT_ITEM_TYPE); val.put(StructuredPostal.POBox,postal.getPoBox()); val.put(StructuredPostal.NEIGHBORHOOD,postal.getExtended()); val.put(StructuredPostal.STREET,postal.getStreet()); val.put(StructuredPostal.CITY,postal.getCity()); val.put(StructuredPostal.REGION,postal.getState()); val.put(StructuredPostal.POSTCODE,postal.getPostalCode()); val.put(StructuredPostal.COUNTRY,postal.getCountry()); val.put(StructuredPostal.FORMATTED_ADDRESS,postal.toString()); val.put(StructuredPostal.IS_PRIMARY,postal.isPrimary() ? 1 : 0); val.put(StructuredPostal.LABEL,postal.getLabel()); val.put(StructuredPostal.TYPE,postal.getType()); return val; }
private boolean updatePostal(Address postal,String rawContactId,Context ctx) { // seek for raw contact + formatted address = same String[] proj = new String[] { StructuredPostal.RAW_CONTACT_ID,Data.MIMETYPE,StructuredPostal.FORMATTED_ADDRESS }; String where = StructuredPostal.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=? AND " + StructuredPostal.FORMATTED_ADDRESS + "=?"; String[] args = new String[] { rawContactId,StructuredPostal.CONTENT_ITEM_TYPE,postal.toString() }; ContentValues values = valuesPostal(postal); values.put(StructuredPostal.RAW_CONTACT_ID,rawContactId); return updateDaTarow(ctx,proj,where,args,values); }
private void fillFromCursor() { Integer type = getInt(StructuredPostal.TYPE); label = getType(type,getString(StructuredPostal.LABEL)); formattedAddress = getString(StructuredPostal.FORMATTED_ADDRESS); poBox = getString(StructuredPostal.POBox); street = getString(StructuredPostal.STREET); neighborhood = getString(StructuredPostal.NEIGHBORHOOD); city = getString(StructuredPostal.CITY); region = getString(StructuredPostal.REGION); postcode = getString(StructuredPostal.POSTCODE); country = getString(StructuredPostal.COUNTRY); }
private String getType(Integer type,String label) { if (type == null) { throw new InvalidCursorTypeException(); } switch (type) { case StructuredPostal.TYPE_HOME: return "home"; case StructuredPostal.TYPE_WORK: return "work"; case StructuredPostal.TYPE_OTHER: return "other"; default: return label; } }
private void initAddresstypesMap() { if (mAddresstypesMap != null) { return; } mAddresstypesMap = new HashMap<String,Integer>(); mAddresstypesMap.put("home",StructuredPostal.TYPE_HOME); mAddresstypesMap.put("work",StructuredPostal.TYPE_WORK); }
public ContactOperations addAddress(String city,int androidAddresstype,boolean isSuperPrimary) { mValues.clear(); mValues.put(StructuredPostal.CITY,country); mValues.put(StructuredPostal.MIMETYPE,StructuredPostal.CONTENT_ITEM_TYPE); if (!TextUtils.isEmpty(label)) { mValues.put(StructuredPostal.LABEL,label); } if (isSuperPrimary) { mValues.put(Email.IS_SUPER_PRIMARY,1); } if (isPrimary) { mValues.put(Email.IS_PRIMARY,1); } mValues.put(StructuredPostal.NEIGHBORHOOD,street); addInsertOp(); return this; }
public static int getAndroidAddresstype(Addresstype type) { switch (type) { case TYPE_CUSTOM: return StructuredPostal.TYPE_CUSTOM; case TYPE_HOME: return StructuredPostal.TYPE_HOME; case TYPE_OTHER: return StructuredPostal.TYPE_OTHER; case TYPE_WORK: return StructuredPostal.TYPE_WORK; default: return StructuredPostal.TYPE_OTHER; } }
public static Addresstype getAddresstype(int androidType) { switch (androidType) { case StructuredPostal.TYPE_CUSTOM: return Addresstype.TYPE_CUSTOM; case StructuredPostal.TYPE_HOME: return Addresstype.TYPE_HOME; case StructuredPostal.TYPE_OTHER: return Addresstype.TYPE_OTHER; case StructuredPostal.TYPE_WORK: return Addresstype.TYPE_WORK; default: return Addresstype.TYPE_OTHER; } }
protected void populatePostalAddresses(Contact c) throws remoteexception { @Cleanup Cursor cursor = providerClient.query(dataURI(),new String[] { /* 0 */ StructuredPostal.FORMATTED_ADDRESS,StructuredPostal.TYPE,StructuredPostal.LABEL,/* 3 */ StructuredPostal.STREET,StructuredPostal.POBox,StructuredPostal.NEIGHBORHOOD,/* 6 */ StructuredPostal.CITY,StructuredPostal.REGION,StructuredPostal.POSTCODE,/* 9 */ StructuredPostal.COUNTRY },StructuredPostal.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?",new String[] { String.valueOf(c.getLocalID()),StructuredPostal.CONTENT_ITEM_TYPE },null); while (cursor != null && cursor.movetoNext()) { Address address = new Address(); address.setLabel(cursor.getString(0)); switch (cursor.getInt(1)) { case StructuredPostal.TYPE_HOME: address.addType(Addresstype.HOME); break; case StructuredPostal.TYPE_WORK: address.addType(Addresstype.WORK); break; case StructuredPostal.TYPE_CUSTOM: String customType = cursor.getString(2); if (!StringUtils.isEmpty(customType)) address.addType(Addresstype.get(labelToXName(customType))); break; } address.setStreetAddress(cursor.getString(3)); address.setPoBox(cursor.getString(4)); address.setExtendedAddress(cursor.getString(5)); address.setLocality(cursor.getString(6)); address.setRegion(cursor.getString(7)); address.setPostalCode(cursor.getString(8)); address.setCountry(cursor.getString(9)); c.getAddresses().add(address); } }
private String getStructuredPostalTypeLabel(int type,String label) { switch (type) { case StructuredPostal.TYPE_HOME: return getString(R.string.label_hoMetag); case StructuredPostal.TYPE_WORK: return getString(R.string.label_worktag); case StructuredPostal.TYPE_OTHER: return getString(R.string.label_othertag); default: return StructuredPostal.getTypeLabel(this.getResources(),label).toString(); } }
@Override public String[] getProjpostal() { return new String[] { StructuredPostal.MIMETYPE,StructuredPostal.IS_PRIMARY,StructuredPostal.STREET,StructuredPostal.CITY,StructuredPostal.COUNTRY,StructuredPostal.FORMATTED_ADDRESS }; }
private String getAddress(String contactId) { Cursor cursor = cr.query( ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId,null); if (cursor.movetoFirst()) { // �������еĵ�ַ String street = cursor .getString(cursor .getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET)); String city = cursor .getString(cursor .getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)); String country = cursor .getString(cursor .getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)); if (country == null) { country = ""; } if (street == null) { street = ""; } if (city == null) { city = ""; } cursor.close(); return country + city + street; } else { cursor.close(); return ""; } }
public static void removeContactLocations(Context c,Account account){ ContactsSyncAdapterService.mContentResolver = c.getContentResolver(); HashMap<String,ContactsSyncAdapterService.SyncEntry> localContacts = ContactsSyncAdapterService.getLocalContacts(account); for (ContactsSyncAdapterService.SyncEntry s : localContacts.values()){ ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI,ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.Data.RAW_CONTACT_ID + " = " + s.raw_id,null); } }
public static void updateContactLocation(long rawContactId,String location){ if ((location == null || location.equals(""))){ return; } String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId + "' AND " + ContactsContract.Data.MIMETYPE + " = '" + StructuredPostal.CONTENT_ITEM_TYPE + "'"; String[] projection = {StructuredPostal.FORMATTED_ADDRESS}; Cursor cursor = ContactsSyncAdapterService.mContentResolver.query(ContactsContract.Data.CONTENT_URI,projection,null); boolean insert = false; if (cursor.getCount() == 0){ insert = true; } else{ cursor.movetoFirst(); String oldloc = cursor.getString(cursor.getColumnIndex(StructuredPostal.FORMATTED_ADDRESS)); if ((oldloc == null) || (!oldloc.equals(location))){ ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI,null); insert = true; } } cursor.close(); if (insert){ ContentValues contentValues = new ContentValues(); //op.put(ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID,); contentValues.put(ContactsContract.Data.MIMETYPE,StructuredPostal.CONTENT_ITEM_TYPE); contentValues.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId); contentValues.put(StructuredPostal.FORMATTED_ADDRESS,location); try { ContactsSyncAdapterService.mContentResolver.insert(ContactsContract.Data.CONTENT_URI,contentValues); // mContentResolver.applyBatch(ContactsContract.AUTHORITY,operationList); } catch (Exception e) { e.printstacktrace(); //Log.e("ERROR:",e.^); } } }
private int getAddresstype(String addresstype) { initAddresstypesMap(); Integer type = mAddresstypesMap.get(addresstype.toLowerCase()); return type != null ? type : StructuredPostal.TYPE_CUSTOM; }
protected Builder buildAddress(Builder builder,Address address) { /* street po.Box (extended) * region * postal code city * country */ String formattedAddress = address.getLabel(); if (StringUtils.isEmpty(formattedAddress)) { String linestreet = StringUtils.join(new String[] { address.getStreetAddress(),address.getPoBox(),address.getExtendedAddress() }," "),lineLocality = StringUtils.join(new String[] { address.getPostalCode(),address.getLocality() }," "); List<String> lines = new LinkedList<String>(); if (linestreet != null) lines.add(linestreet); if (address.getRegion() != null && !address.getRegion().isEmpty()) lines.add(address.getRegion()); if (lineLocality != null) lines.add(lineLocality); formattedAddress = StringUtils.join(lines,"\n"); } int typeCode = 0; String typeLabel = null; for (Addresstype type : address.getTypes()) if (type == Addresstype.HOME) typeCode = StructuredPostal.TYPE_HOME; else if (type == Addresstype.WORK) typeCode = StructuredPostal.TYPE_WORK; if (typeCode == 0) if (address.getTypes().isEmpty()) typeCode = StructuredPostal.TYPE_OTHER; else { typeCode = StructuredPostal.TYPE_CUSTOM; typeLabel = xNametoLabel(address.getTypes().iterator().next().getValue()); } builder = builder .withValue(Data.MIMETYPE,StructuredPostal.CONTENT_ITEM_TYPE) .withValue(StructuredPostal.FORMATTED_ADDRESS,formattedAddress) .withValue(StructuredPostal.TYPE,typeCode) .withValue(StructuredPostal.STREET,address.getStreetAddress()) .withValue(StructuredPostal.POBox,address.getPoBox()) .withValue(StructuredPostal.NEIGHBORHOOD,address.getExtendedAddress()) .withValue(StructuredPostal.CITY,address.getLocality()) .withValue(StructuredPostal.REGION,address.getRegion()) .withValue(StructuredPostal.POSTCODE,address.getPostalCode()) .withValue(StructuredPostal.COUNTRY,address.getCountry()); if (typeLabel != null) builder = builder.withValue(StructuredPostal.LABEL,typeLabel); return builder; }
@Override public String getQueryPostal() { return StructuredPostal.MIMETYPE + " = " + DatabaseUtils.sqlEscapestring("" + StructuredPostal.CONTENT_ITEM_TYPE); }
public static void updateContactLocation(long rawContactId,String city){ if ((country == null || country.equals("")) && (region == null || region.equals("")) && (city == null || city.equals(""))){ return; } String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId + "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + "'"; String[] projection = {ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,ContactsContract.CommonDataKinds.StructuredPostal.REGION,ContactsContract.CommonDataKinds.StructuredPostal.CITY}; Cursor cursor = ContactsSyncAdapterService.mContentResolver.query(ContactsContract.Data.CONTENT_URI,null); boolean insert = false; if (cursor.getCount() == 0){ insert = true; } else{ cursor.movetoFirst(); String oldCountry = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)); String oldRegion = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION)); String oldCity = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)); if ((oldCountry != null && !oldCountry.equals(country)) || (oldRegion != null && !oldRegion.equals(region)) || (oldCity != null && oldCity.equals(city))){ ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI,ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE); contentValues.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId); if (country != null && ! country.equals("")){ contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY,country); } if (region != null && ! region.equals("")){ contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION,region); } if (city != null && ! city.equals("")){ contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY,city); } try { ContactsSyncAdapterService.mContentResolver.insert(ContactsContract.Data.CONTENT_URI,contentValues); // mContentResolver.applyBatch(ContactsContract.AUTHORITY,e.^); } } }
ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidatorProvider
DataAnnotationsModelValidator最终是通过它对应的ModelValidatorProvider,即DataAnnotationsModelValidatorProvider创建的。通过前面的介绍我们知道它是AssociatedValidatorProvider的子类,后者在用于获取ModelValidator的GetValidators方法中已经根据指定的Model元数据所有特性创建出来,DataAnnotationsModelValidator只需要从中筛选出继承自ValiationAttribute的验证特性并创建对象的DataAnnotationsModelValidator就可以了。[本文已经同步到《How ASP.NET MVC Works?》中]
目录
DataAnnotationsModelValidator
基于ValidationAttribute的ModelValidator的创建
基于IValidatableObject的ModelValidator的创建
默认的ModelValidator创建机制
对ModelValidator创建方式的定制
DataAnnotationsModelValidator
我们现在结合DataAnnotationsModelValidator的相关定义来讨论一下具体的ModelValidator提供机制。如下面的代码片断所示,DataAnnotationsModelValidatorProvider具有两个静态的字段AttributeFactories和DefaultAttributeFactory,后者是一个DataAnnotationsModelValidationFactory委托,前者是以此委托为Value以Type对象为Key的字典。
1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
2: {
3: //其他成员
4: internal static readonly Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories;
5: internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory;
6:
7: internal static DataAnnotationsValidatableObjectAdapterFactory DefaultValidatableFactory;
8: internal static readonly Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory> ValidatableFactories;
9:
10: protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, HttpActionContext actionContext, IEnumerable<Attribute> attributes);
11: }
12:
13: public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
14:
15: public delegate ModelValidator DataAnnotationsValidatableObjectAdapterFactory(ModelMetadata metadata, ControllerContext context);
基于ValidationAttribute的ModelValidator的创建
委托DataAnnotationsModelValidationFactory根据ModelMetadata、ControllerContext和ValidationAttribute返回一个ModelValidator对象,而字段AttributeFactories表示的字典对象的Key是具体的验证特性的类型,也就是说它维护一个ValidationAttribute特性类型和对应ModelValidator工厂的匹配关系。在重写的GetValidators方法中,针对指定的每一个ValidationAttribute,它先根据其类型从AttributeFactories中获取一个对应的DataAnnotationsModelValidationFactory委托,如果该委托存在,则用它来创建相应的ModelValidator对象;否则就采用字段DefaultAttributeFactory表示的DataAnnotationsModelValidationFactory委托来进行ModelValidator的创建。
基于IValidatableObject的ModelValidator的创建
除了AttributeFactories和DefaultAttributeFactory,DataAnnotationsModelValidatorProvider还具有DefaultValidatableFactory和ValidatableFactories这两个静态属性,它们用于针对可验证对象(实现了IValidatableObject接口)的ModelValidator的创建。DataAnnotationsModelValidator的类型是另外一个类型为DataAnnotationsValidatableObjectAdapterFactory的委托,该委托根据ModelMetadata和ControllerContext创建相应的ModelValidator。ValidatableFactories是一个以此委托为Value,以Type对象为Key的字典。
当DataAnnotationsModelValidatorProvider完成了针对基于验证特性的ModelValidator的创建之后,如果根据Model元数据解析出来的Model类型实现了IValidatableObject接口,那么先从字典ValidatableFactories中根据此类型获取一个对应的DataAnnotationsValidatableObjectAdapterFactory委托,如果匹配的委托对象存在,则用其进行ModelValidator的创建;否则采用通过字段DefaultValidatableFactory表示的默认工厂来创建相应的ModelValidator对象。
默认的ModelValidator创建机制
在DataAnnotationsModelValidatorProvider类型被加载的时候,上述的四个字段会在静态构造函数调用时被初始化。从如下的代码片断可看出,对于一般的ValidationAttribute,对应的ModelValidator是一个DataAnnotationsModelValidator对象(DefaultAttributeFactory字段);针对RangeAttribute、RegularExpressionAttribute 、RequiredAttribute和StringLengthAttribute这四种验证特性,它们对应的适配ModelValidator会被创建出来。而对于可验证对象来说,默认情况下提供的ModelValidator列表中还包含一个ValidatableObjectAdapter对象。
1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
2: {
3: //其他成员
4: static DataAnnotationsModelValidatorProvider()
5: {
6: //1、DefaultAttributeFactory
7: DefaultAttributeFactory = (metadata, context, attribute) => new DataAnnotationsModelValidator(metadata, context, attribute);
8:
9: //2、AttributeFactories
10: Dictionary<Type, DataAnnotationsModelValidationFactory> dictionary = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
11: dictionary.Add(typeof(RangeAttribute), (metadata, context, attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute));
12: dictionary.Add(typeof(RegularExpressionAttribute), (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute));
13: dictionary.Add(typeof(RequiredAttribute), (metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute));
14: dictionary.Add(typeof(StringLengthAttribute), (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context,(StringLengthAttribute)attribute));
15: AttributeFactories = dictionary;
16:
17: //3、DefaultValidatableFactory
18: DefaultValidatableFactory = (metadata, context) => new ValidatableObjectAdapter(metadata, context);
19:
20: //4、ValidatableFactories
21: ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
22: }
23: }